From fd947bd852c29760e0831a7182f0b3231ea7d9ad Mon Sep 17 00:00:00 2001 From: Lukas Nowy Date: Sun, 16 Dec 2018 19:08:08 +0100 Subject: [PATCH] https MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit express server läuft jetzt mit https --- express-server/LICENSE | 41 + express-server/examples/demo.js | 75 + express-server/examples/force-renew.js | 29 + express-server/examples/http2.js | 74 + express-server/examples/my-express-app.js | 15 + express-server/examples/production.js | 90 + express-server/examples/quickstart.js | 36 + express-server/examples/remote-access.js | 95 + express-server/examples/spdy.js | 68 + express-server/examples/vhost.js | 114 + express-server/examples/websockets.js | 40 + express-server/index.js | 159 + express-server/node_modules/.bin/certpem | 52 + express-server/node_modules/.bin/mkdirp | 33 + .../node_modules/.bin/rsa-keygen-js | 35 + .../node_modules/@coolaj86/urequest/LICENSE | 41 + .../node_modules/@coolaj86/urequest/README.md | 339 + .../node_modules/@coolaj86/urequest/index.js | 425 + .../@coolaj86/urequest/package.json | 90 + express-server/node_modules/acme-v2/.jshintrc | 18 + express-server/node_modules/acme-v2/LICENSE | 41 + express-server/node_modules/acme-v2/README.md | 221 + express-server/node_modules/acme-v2/compat.js | 77 + .../node_modules/acme-v2/examples/cli.js | 68 + .../acme-v2/examples/genkeypair.js | 22 + .../acme-v2/examples/http-server.js | 7 + .../acme-v2/examples/https-server.js | 11 + express-server/node_modules/acme-v2/node.js | 719 ++ .../node_modules/acme-v2/package.json | 102 + .../node_modules/acme-v2/tests/cb.js | 79 + .../node_modules/acme-v2/tests/compat.js | 68 + .../acme-v2/tests/fullchain-formats.js | 77 + .../node_modules/acme-v2/tests/promise.js | 85 + express-server/node_modules/acme/LICENSE | 41 + express-server/node_modules/acme/README.md | 233 + .../node_modules/acme/examples/cli.js | 64 + .../node_modules/acme/examples/genkeypair.js | 22 + .../node_modules/acme/examples/http-server.js | 7 + .../acme/examples/https-server.js | 11 + express-server/node_modules/acme/node.js | 3 + express-server/node_modules/acme/package.json | 109 + .../node_modules/acme/tests/promise.js | 85 + .../node_modules/asn1js/.gitattributes | 63 + express-server/node_modules/asn1js/.npmignore | 156 + express-server/node_modules/asn1js/CNAME | 1 + express-server/node_modules/asn1js/LICENSE | 30 + express-server/node_modules/asn1js/README.md | 212 + .../asn1js/examples/ASN.1 usage/asn1_usage.js | 240 + .../node_modules/asn1js/org/pkijs/asn1.js | 5466 ++++++++++++ .../node_modules/asn1js/org/pkijs/common.js | 1541 ++++ .../node_modules/asn1js/package.json | 94 + .../node_modules/async-limiter/.travis.yml | 7 + .../node_modules/async-limiter/LICENSE | 8 + .../async-limiter/coverage/coverage.json | 1 + .../lcov-report/async-throttle/index.html | 73 + .../lcov-report/async-throttle/index.js.html | 246 + .../coverage/lcov-report/base.css | 182 + .../coverage/lcov-report/index.html | 73 + .../coverage/lcov-report/prettify.css | 1 + .../coverage/lcov-report/prettify.js | 1 + .../lcov-report/sort-arrow-sprite.png | Bin 0 -> 209 bytes .../coverage/lcov-report/sorter.js | 156 + .../async-limiter/coverage/lcov.info | 74 + .../node_modules/async-limiter/index.js | 67 + .../node_modules/async-limiter/package.json | 97 + .../node_modules/async-limiter/readme.md | 132 + express-server/node_modules/batch/.npmignore | 4 + express-server/node_modules/batch/History.md | 93 + express-server/node_modules/batch/LICENSE | 22 + express-server/node_modules/batch/Makefile | 6 + express-server/node_modules/batch/Readme.md | 53 + .../node_modules/batch/component.json | 14 + express-server/node_modules/batch/index.js | 173 + .../node_modules/batch/package.json | 84 + .../node_modules/bindings/README.md | 98 + .../node_modules/bindings/bindings.js | 174 + .../node_modules/bindings/package.json | 88 + express-server/node_modules/bluebird/LICENSE | 21 + .../node_modules/bluebird/README.md | 57 + .../node_modules/bluebird/changelog.md | 1 + .../bluebird/js/browser/bluebird.core.js | 3805 +++++++++ .../bluebird/js/browser/bluebird.core.min.js | 31 + .../bluebird/js/browser/bluebird.js | 5647 +++++++++++++ .../bluebird/js/browser/bluebird.min.js | 31 + .../node_modules/bluebird/js/release/any.js | 21 + .../bluebird/js/release/assert.js | 55 + .../node_modules/bluebird/js/release/async.js | 165 + .../node_modules/bluebird/js/release/bind.js | 67 + .../bluebird/js/release/bluebird.js | 11 + .../bluebird/js/release/call_get.js | 123 + .../bluebird/js/release/cancel.js | 129 + .../bluebird/js/release/catch_filter.js | 42 + .../bluebird/js/release/context.js | 69 + .../bluebird/js/release/debuggability.js | 934 +++ .../bluebird/js/release/direct_resolve.js | 46 + .../node_modules/bluebird/js/release/each.js | 30 + .../bluebird/js/release/errors.js | 116 + .../node_modules/bluebird/js/release/es5.js | 80 + .../bluebird/js/release/filter.js | 12 + .../bluebird/js/release/finally.js | 146 + .../bluebird/js/release/generators.js | 223 + .../node_modules/bluebird/js/release/join.js | 168 + .../node_modules/bluebird/js/release/map.js | 168 + .../bluebird/js/release/method.js | 55 + .../bluebird/js/release/nodeback.js | 51 + .../bluebird/js/release/nodeify.js | 58 + .../bluebird/js/release/promise.js | 776 ++ .../bluebird/js/release/promise_array.js | 185 + .../bluebird/js/release/promisify.js | 314 + .../node_modules/bluebird/js/release/props.js | 118 + .../node_modules/bluebird/js/release/queue.js | 73 + .../node_modules/bluebird/js/release/race.js | 49 + .../bluebird/js/release/reduce.js | 172 + .../bluebird/js/release/schedule.js | 61 + .../bluebird/js/release/settle.js | 43 + .../node_modules/bluebird/js/release/some.js | 148 + .../js/release/synchronous_inspection.js | 103 + .../bluebird/js/release/thenables.js | 86 + .../bluebird/js/release/timers.js | 93 + .../node_modules/bluebird/js/release/using.js | 226 + .../node_modules/bluebird/js/release/util.js | 384 + .../node_modules/bluebird/package.json | 130 + express-server/node_modules/certpem/LICENSE | 21 + express-server/node_modules/certpem/README.md | 65 + .../node_modules/certpem/bin/certpem.js | 52 + express-server/node_modules/certpem/cert.pem | 31 + express-server/node_modules/certpem/index.js | 120 + .../node_modules/certpem/package.json | 105 + express-server/node_modules/certpem/test.js | 3 + .../express-basic-auth/.circleci/config.yml | 37 + .../node_modules/express-basic-auth/README.md | 205 + .../express-basic-auth/example.js | 132 + .../express-basic-auth.d.ts | 137 + .../node_modules/express-basic-auth/index.js | 82 + .../express-basic-auth/package.json | 100 + .../node_modules/express-basic-auth/test.js | 256 + express-server/node_modules/greenlock/LICENSE | 41 + .../node_modules/greenlock/README.md | 567 ++ .../node_modules/greenlock/index.js | 597 ++ .../node_modules/greenlock/lib/community.js | 51 + .../node_modules/greenlock/lib/core.js | 459 ++ .../node_modules/greenlock/lib/middleware.js | 68 + .../node_modules/greenlock/lib/utils.js | 127 + .../node_modules/greenlock/package.json | 124 + .../node_modules/ipaddr.js/lib/ipaddr.js.d.ts | 71 + .../node_modules/le-challenge-fs/.npmignore | 37 + .../node_modules/le-challenge-fs/LICENSE | 21 + .../node_modules/le-challenge-fs/README.md | 63 + .../node_modules/le-challenge-fs/index.js | 121 + .../node_modules/le-challenge-fs/package.json | 100 + .../node_modules/le-challenge-fs/test.js | 72 + .../node_modules/le-sni-auto/LICENSE | 21 + .../node_modules/le-sni-auto/README.md | 194 + .../node_modules/le-sni-auto/index.js | 172 + .../node_modules/le-sni-auto/package.json | 98 + .../node_modules/le-sni-auto/test.js | 205 + .../node_modules/le-store-certbot/LICENSE | 21 + .../node_modules/le-store-certbot/README.md | 75 + .../node_modules/le-store-certbot/index.js | 661 ++ .../le-store-certbot/package.json | 97 + .../le-store-certbot/renewal.conf.tpl | 83 + .../node_modules/minimist/.travis.yml | 4 + express-server/node_modules/minimist/LICENSE | 18 + .../node_modules/minimist/example/parse.js | 2 + express-server/node_modules/minimist/index.js | 187 + .../node_modules/minimist/package.json | 93 + .../node_modules/minimist/readme.markdown | 73 + .../node_modules/minimist/test/dash.js | 24 + .../minimist/test/default_bool.js | 20 + .../node_modules/minimist/test/dotted.js | 16 + .../node_modules/minimist/test/long.js | 31 + .../node_modules/minimist/test/parse.js | 318 + .../minimist/test/parse_modified.js | 9 + .../node_modules/minimist/test/short.js | 67 + .../node_modules/minimist/test/whitespace.js | 8 + .../node_modules/mkdirp/.travis.yml | 8 + express-server/node_modules/mkdirp/LICENSE | 21 + express-server/node_modules/mkdirp/bin/cmd.js | 33 + .../node_modules/mkdirp/bin/usage.txt | 12 + .../node_modules/mkdirp/examples/pow.js | 6 + express-server/node_modules/mkdirp/index.js | 98 + .../node_modules/mkdirp/package.json | 86 + .../node_modules/mkdirp/readme.markdown | 100 + .../node_modules/mkdirp/test/chmod.js | 41 + .../node_modules/mkdirp/test/clobber.js | 38 + .../node_modules/mkdirp/test/mkdirp.js | 28 + .../node_modules/mkdirp/test/opts_fs.js | 29 + .../node_modules/mkdirp/test/opts_fs_sync.js | 27 + .../node_modules/mkdirp/test/perm.js | 32 + .../node_modules/mkdirp/test/perm_sync.js | 36 + .../node_modules/mkdirp/test/race.js | 37 + .../node_modules/mkdirp/test/rel.js | 32 + .../node_modules/mkdirp/test/return.js | 25 + .../node_modules/mkdirp/test/return_sync.js | 24 + .../node_modules/mkdirp/test/root.js | 19 + .../node_modules/mkdirp/test/sync.js | 32 + .../node_modules/mkdirp/test/umask.js | 28 + .../node_modules/mkdirp/test/umask_sync.js | 32 + express-server/node_modules/nan/CHANGELOG.md | 509 ++ express-server/node_modules/nan/LICENSE.md | 13 + express-server/node_modules/nan/README.md | 456 + .../node_modules/nan/doc/asyncworker.md | 146 + .../node_modules/nan/doc/buffers.md | 54 + .../node_modules/nan/doc/callback.md | 76 + .../node_modules/nan/doc/converters.md | 41 + express-server/node_modules/nan/doc/errors.md | 226 + express-server/node_modules/nan/doc/json.md | 62 + .../node_modules/nan/doc/maybe_types.md | 583 ++ .../node_modules/nan/doc/methods.md | 661 ++ express-server/node_modules/nan/doc/new.md | 147 + .../node_modules/nan/doc/node_misc.md | 123 + .../node_modules/nan/doc/object_wrappers.md | 263 + .../node_modules/nan/doc/persistent.md | 296 + express-server/node_modules/nan/doc/scopes.md | 73 + express-server/node_modules/nan/doc/script.md | 38 + .../node_modules/nan/doc/string_bytes.md | 62 + .../node_modules/nan/doc/v8_internals.md | 199 + .../node_modules/nan/doc/v8_misc.md | 85 + .../node_modules/nan/include_dirs.js | 1 + express-server/node_modules/nan/nan.h | 2810 +++++++ .../node_modules/nan/nan_callbacks.h | 88 + .../node_modules/nan/nan_callbacks_12_inl.h | 514 ++ .../nan/nan_callbacks_pre_12_inl.h | 520 ++ .../node_modules/nan/nan_converters.h | 72 + .../node_modules/nan/nan_converters_43_inl.h | 48 + .../nan/nan_converters_pre_43_inl.h | 42 + .../nan/nan_define_own_property_helper.h | 29 + .../nan/nan_implementation_12_inl.h | 424 + .../nan/nan_implementation_pre_12_inl.h | 263 + express-server/node_modules/nan/nan_json.h | 166 + .../node_modules/nan/nan_maybe_43_inl.h | 369 + .../node_modules/nan/nan_maybe_pre_43_inl.h | 316 + express-server/node_modules/nan/nan_new.h | 340 + .../node_modules/nan/nan_object_wrap.h | 158 + .../node_modules/nan/nan_persistent_12_inl.h | 132 + .../nan/nan_persistent_pre_12_inl.h | 242 + express-server/node_modules/nan/nan_private.h | 73 + .../node_modules/nan/nan_string_bytes.h | 305 + .../nan/nan_typedarray_contents.h | 90 + express-server/node_modules/nan/nan_weak.h | 437 + express-server/node_modules/nan/package.json | 135 + express-server/node_modules/nan/tools/1to2.js | 412 + .../node_modules/nan/tools/README.md | 14 + .../node_modules/nan/tools/package.json | 19 + .../node_modules/pkijs/.gitattributes | 63 + express-server/node_modules/pkijs/.npmignore | 1 + express-server/node_modules/pkijs/LICENSE | 30 + express-server/node_modules/pkijs/README.md | 287 + .../pkijs/org/pkijs/cms_schema.js | 1259 +++ .../node_modules/pkijs/org/pkijs/cms_simpl.js | 6933 ++++++++++++++++ .../node_modules/pkijs/org/pkijs/common.js | 1559 ++++ .../pkijs/org/pkijs/ocsp_tsp_schema.js | 833 ++ .../pkijs/org/pkijs/ocsp_tsp_simpl.js | 3089 +++++++ .../pkijs/org/pkijs/pkcs12_schema.js | 413 + .../pkijs/org/pkijs/pkcs12_simpl.js | 2069 +++++ .../pkijs/org/pkijs/x509_schema.js | 1889 +++++ .../pkijs/org/pkijs/x509_simpl.js | 7301 +++++++++++++++++ .../node_modules/pkijs/package.json | 96 + express-server/node_modules/pyconf/LICENSE | 202 + express-server/node_modules/pyconf/README.md | 62 + .../node_modules/pyconf/example.conf | 62 + express-server/node_modules/pyconf/index.js | 184 + .../node_modules/pyconf/package.json | 90 + express-server/node_modules/pyconf/test.js | 26 + .../node_modules/redirect-https/LICENSE | 202 + .../node_modules/redirect-https/README.md | 113 + .../node_modules/redirect-https/example.js | 15 + .../node_modules/redirect-https/index.js | 97 + .../node_modules/redirect-https/package.json | 93 + .../node_modules/redirect-https/test.js | 77 + .../node_modules/rsa-compat/LICENSE | 375 + .../node_modules/rsa-compat/README.md | 279 + .../node_modules/rsa-compat/bin/rsa-keygen.js | 35 + .../node_modules/rsa-compat/fixtures/csr.pem | 11 + .../rsa-compat/fixtures/csr.urlbase64 | 1 + .../rsa-compat/fixtures/privkey.jwk.json | 11 + .../rsa-compat/fixtures/privkey.pkcs1.pem | 15 + .../rsa-compat/fixtures/privkey.pkcs8.pem | 16 + .../rsa-compat/fixtures/signed.jwk.json | 13 + .../node_modules/rsa-compat/index.js | 7 + .../rsa-compat/lib/generate-privkey-forge.js | 57 + .../rsa-compat/lib/generate-privkey-node.js | 39 + .../rsa-compat/lib/generate-privkey-ursa.js | 32 + .../rsa-compat/lib/generate-privkey.js | 66 + .../rsa-compat/lib/rasha/README.md | 218 + .../rsa-compat/lib/rasha/bin/rasha.js | 97 + .../rasha/fixtures/privkey-rsa-2048.jwk.json | 11 + .../rasha/fixtures/privkey-rsa-2048.pkcs1.pem | 27 + .../rasha/fixtures/privkey-rsa-2048.pkcs8.pem | 28 + .../lib/rasha/fixtures/pub-rsa-2048.jwk.json | 5 + .../lib/rasha/fixtures/pub-rsa-2048.pkcs1.pem | 8 + .../lib/rasha/fixtures/pub-rsa-2048.spki.pem | 9 + .../lib/rasha/fixtures/pub-rsa-2048.ssh.pub | 1 + .../rsa-compat/lib/rasha/index.js | 2 + .../rsa-compat/lib/rasha/lib/asn1.js | 235 + .../rsa-compat/lib/rasha/lib/encoding.js | 104 + .../rsa-compat/lib/rasha/lib/pem.js | 28 + .../rsa-compat/lib/rasha/lib/rasha.js | 204 + .../rsa-compat/lib/rasha/lib/ssh.js | 80 + .../rsa-compat/lib/rasha/lib/telemetry.js | 111 + .../rsa-compat/lib/rasha/lib/x509.js | 153 + .../rsa-compat/lib/rsa-csr/README.md | 214 + .../rsa-compat/lib/rsa-csr/bin/rsa-csr.js | 23 + .../rsa-csr/fixtures/example.com-www.csr.pem | 16 + .../fixtures/privkey-rsa-2048.jwk.json | 11 + .../fixtures/privkey-rsa-2048.pkcs1.pem | 27 + .../fixtures/whatever.net-www-api.csr.pem | 17 + .../rsa-compat/lib/rsa-csr/index.js | 2 + .../rsa-compat/lib/rsa-csr/lib/asn1.js | 72 + .../rsa-compat/lib/rsa-csr/lib/csr.js | 152 + .../rsa-compat/lib/rsa-csr/lib/encoding.js | 34 + .../rsa-compat/lib/rsa-csr/lib/pem.js | 12 + .../rsa-compat/lib/rsa-csr/lib/telemetry.js | 111 + .../rsa-compat/lib/rsa-csr/lib/x509.js | 66 + .../node_modules/rsa-compat/lib/rsa.js | 213 + .../node_modules/rsa-compat/lib/telemetry.js | 111 + .../node_modules/rsa-compat/package.json | 108 + .../node_modules/rsa-compat/test.sh | 8 + .../rsa-compat/tests/generate-csr.js | 26 + .../rsa-compat/tests/generate-key-new.js | 33 + .../rsa-compat/tests/generate-key.js | 31 + .../rsa-compat/tests/generate-sig.js | 54 + .../node_modules/rsa-compat/tests/privkey.jwk | 1 + .../node_modules/rsa-compat/tests/privkey.pem | 27 + .../rsa-compat/tests/reciprocate.js | 86 + .../node_modules/safe-replace/LICENSE | 202 + .../node_modules/safe-replace/README.md | 86 + .../node_modules/safe-replace/index.js | 118 + .../node_modules/safe-replace/package.json | 93 + .../node_modules/safe-replace/test.js | 11 + .../node_modules/serve-index/HISTORY.md | 305 + .../node_modules/serve-index/LICENSE | 25 + .../node_modules/serve-index/README.md | 154 + .../node_modules/serve-index/index.js | 646 ++ .../node_modules/serve-index/package.json | 99 + .../serve-index/public/directory.html | 82 + .../public/icons/application_xp.png | Bin 0 -> 426 bytes .../public/icons/application_xp_terminal.png | Bin 0 -> 507 bytes .../serve-index/public/icons/box.png | Bin 0 -> 555 bytes .../serve-index/public/icons/cd.png | Bin 0 -> 673 bytes .../serve-index/public/icons/controller.png | Bin 0 -> 666 bytes .../serve-index/public/icons/drive.png | Bin 0 -> 346 bytes .../serve-index/public/icons/film.png | Bin 0 -> 653 bytes .../serve-index/public/icons/folder.png | Bin 0 -> 634 bytes .../serve-index/public/icons/font.png | Bin 0 -> 567 bytes .../serve-index/public/icons/image.png | Bin 0 -> 516 bytes .../serve-index/public/icons/map.png | Bin 0 -> 804 bytes .../serve-index/public/icons/page.png | Bin 0 -> 635 bytes .../serve-index/public/icons/page_add.png | Bin 0 -> 739 bytes .../serve-index/public/icons/page_attach.png | Bin 0 -> 794 bytes .../serve-index/public/icons/page_code.png | Bin 0 -> 818 bytes .../serve-index/public/icons/page_copy.png | Bin 0 -> 663 bytes .../serve-index/public/icons/page_delete.png | Bin 0 -> 740 bytes .../serve-index/public/icons/page_edit.png | Bin 0 -> 807 bytes .../serve-index/public/icons/page_error.png | Bin 0 -> 793 bytes .../serve-index/public/icons/page_excel.png | Bin 0 -> 817 bytes .../serve-index/public/icons/page_find.png | Bin 0 -> 879 bytes .../serve-index/public/icons/page_gear.png | Bin 0 -> 833 bytes .../serve-index/public/icons/page_go.png | Bin 0 -> 779 bytes .../serve-index/public/icons/page_green.png | Bin 0 -> 621 bytes .../serve-index/public/icons/page_key.png | Bin 0 -> 801 bytes .../public/icons/page_lightning.png | Bin 0 -> 839 bytes .../serve-index/public/icons/page_link.png | Bin 0 -> 830 bytes .../public/icons/page_paintbrush.png | Bin 0 -> 813 bytes .../serve-index/public/icons/page_paste.png | Bin 0 -> 703 bytes .../serve-index/public/icons/page_red.png | Bin 0 -> 641 bytes .../serve-index/public/icons/page_refresh.png | Bin 0 -> 858 bytes .../serve-index/public/icons/page_save.png | Bin 0 -> 774 bytes .../serve-index/public/icons/page_white.png | Bin 0 -> 294 bytes .../public/icons/page_white_acrobat.png | Bin 0 -> 591 bytes .../public/icons/page_white_actionscript.png | Bin 0 -> 664 bytes .../public/icons/page_white_add.png | Bin 0 -> 512 bytes .../serve-index/public/icons/page_white_c.png | Bin 0 -> 587 bytes .../public/icons/page_white_camera.png | Bin 0 -> 656 bytes .../public/icons/page_white_cd.png | Bin 0 -> 666 bytes .../public/icons/page_white_code.png | Bin 0 -> 603 bytes .../public/icons/page_white_code_red.png | Bin 0 -> 587 bytes .../public/icons/page_white_coldfusion.png | Bin 0 -> 592 bytes .../public/icons/page_white_compressed.png | Bin 0 -> 724 bytes .../public/icons/page_white_copy.png | Bin 0 -> 309 bytes .../public/icons/page_white_cplusplus.png | Bin 0 -> 621 bytes .../public/icons/page_white_csharp.png | Bin 0 -> 700 bytes .../public/icons/page_white_cup.png | Bin 0 -> 639 bytes .../public/icons/page_white_database.png | Bin 0 -> 579 bytes .../public/icons/page_white_delete.png | Bin 0 -> 536 bytes .../public/icons/page_white_dvd.png | Bin 0 -> 638 bytes .../public/icons/page_white_edit.png | Bin 0 -> 618 bytes .../public/icons/page_white_error.png | Bin 0 -> 623 bytes .../public/icons/page_white_excel.png | Bin 0 -> 663 bytes .../public/icons/page_white_find.png | Bin 0 -> 676 bytes .../public/icons/page_white_flash.png | Bin 0 -> 582 bytes .../public/icons/page_white_freehand.png | Bin 0 -> 639 bytes .../public/icons/page_white_gear.png | Bin 0 -> 402 bytes .../public/icons/page_white_get.png | Bin 0 -> 516 bytes .../public/icons/page_white_go.png | Bin 0 -> 612 bytes .../serve-index/public/icons/page_white_h.png | Bin 0 -> 603 bytes .../public/icons/page_white_horizontal.png | Bin 0 -> 296 bytes .../public/icons/page_white_key.png | Bin 0 -> 616 bytes .../public/icons/page_white_lightning.png | Bin 0 -> 669 bytes .../public/icons/page_white_link.png | Bin 0 -> 614 bytes .../public/icons/page_white_magnify.png | Bin 0 -> 554 bytes .../public/icons/page_white_medal.png | Bin 0 -> 706 bytes .../public/icons/page_white_office.png | Bin 0 -> 779 bytes .../public/icons/page_white_paint.png | Bin 0 -> 688 bytes .../public/icons/page_white_paintbrush.png | Bin 0 -> 618 bytes .../public/icons/page_white_paste.png | Bin 0 -> 620 bytes .../public/icons/page_white_php.png | Bin 0 -> 538 bytes .../public/icons/page_white_picture.png | Bin 0 -> 650 bytes .../public/icons/page_white_powerpoint.png | Bin 0 -> 588 bytes .../public/icons/page_white_put.png | Bin 0 -> 523 bytes .../public/icons/page_white_ruby.png | Bin 0 -> 626 bytes .../public/icons/page_white_stack.png | Bin 0 -> 317 bytes .../public/icons/page_white_star.png | Bin 0 -> 565 bytes .../public/icons/page_white_swoosh.png | Bin 0 -> 634 bytes .../public/icons/page_white_text.png | Bin 0 -> 342 bytes .../public/icons/page_white_text_width.png | Bin 0 -> 315 bytes .../public/icons/page_white_tux.png | Bin 0 -> 668 bytes .../public/icons/page_white_vector.png | Bin 0 -> 644 bytes .../public/icons/page_white_visualstudio.png | Bin 0 -> 702 bytes .../public/icons/page_white_width.png | Bin 0 -> 309 bytes .../public/icons/page_white_word.png | Bin 0 -> 651 bytes .../public/icons/page_white_world.png | Bin 0 -> 734 bytes .../public/icons/page_white_wrench.png | Bin 0 -> 613 bytes .../public/icons/page_white_zip.png | Bin 0 -> 386 bytes .../serve-index/public/icons/page_word.png | Bin 0 -> 777 bytes .../serve-index/public/icons/page_world.png | Bin 0 -> 903 bytes .../node_modules/serve-index/public/style.css | 257 + .../node_modules/ursa-optional/.travis.yml | 19 + .../node_modules/ursa-optional/LICENSE.txt | 194 + .../node_modules/ursa-optional/README.md | 596 ++ .../node_modules/ursa-optional/binding.gyp | 27 + .../node_modules/ursa-optional/build/Makefile | 324 + .../Release/obj.target/ursaNative.node.d | 1 + .../obj.target/ursaNative/src/ursaNative.o.d | 53 + .../Release/.deps/Release/ursaNative.node.d | 1 + .../build/Release/obj.target/ursaNative.node | Bin 0 -> 73184 bytes .../obj.target/ursaNative/src/ursaNative.o | Bin 0 -> 106968 bytes .../build/Release/ursaNative.node | Bin 0 -> 73184 bytes .../ursa-optional/build/binding.Makefile | 6 + .../ursa-optional/build/config.gypi | 153 + .../ursa-optional/build/ursaNative.target.mk | 145 + .../node_modules/ursa-optional/lib/ursa.js | 752 ++ .../node_modules/ursa-optional/package.json | 110 + .../node_modules/ursa-optional/rebuild.js | 17 + .../ursa-optional/src/ursaNative.cc | 1865 +++++ .../ursa-optional/src/ursaNative.h | 56 + .../ursa-optional/test/.eslintrc.json | 5 + .../ursa-optional/test/another_zorch.pem | 15 + .../ursa-optional/test/blort-pass.pem | 30 + .../node_modules/ursa-optional/test/blort.pem | 27 + .../node_modules/ursa-optional/test/blort.pub | 9 + .../ursa-optional/test/blort.sshpub | 1 + .../ursa-optional/test/fixture.js | 215 + .../node_modules/ursa-optional/test/native.js | 752 ++ .../ursa-optional/test/pss_tv.pub | 6 + .../node_modules/ursa-optional/test/test.js | 608 ++ .../node_modules/ursa-optional/test/zorch.pem | 27 + .../node_modules/ursa-optional/test/zorch.pub | 9 + .../node_modules/utils-merge/.npmignore | 9 + express-server/node_modules/ws/LICENSE | 21 + express-server/node_modules/ws/README.md | 417 + express-server/node_modules/ws/index.js | 9 + .../node_modules/ws/lib/buffer-util.js | 72 + .../node_modules/ws/lib/constants.js | 10 + .../node_modules/ws/lib/event-target.js | 170 + .../node_modules/ws/lib/extension.js | 211 + .../node_modules/ws/lib/permessage-deflate.js | 516 ++ .../node_modules/ws/lib/receiver.js | 513 ++ express-server/node_modules/ws/lib/sender.js | 401 + .../node_modules/ws/lib/validation.js | 29 + .../node_modules/ws/lib/websocket-server.js | 357 + .../node_modules/ws/lib/websocket.js | 828 ++ express-server/node_modules/ws/package.json | 122 + express-server/public/javascripts/test.js | 97 + express-server/test/greenlock.js | 75 + 475 files changed, 91128 insertions(+) create mode 100644 express-server/LICENSE create mode 100644 express-server/examples/demo.js create mode 100644 express-server/examples/force-renew.js create mode 100644 express-server/examples/http2.js create mode 100644 express-server/examples/my-express-app.js create mode 100644 express-server/examples/production.js create mode 100644 express-server/examples/quickstart.js create mode 100644 express-server/examples/remote-access.js create mode 100644 express-server/examples/spdy.js create mode 100644 express-server/examples/vhost.js create mode 100644 express-server/examples/websockets.js create mode 100644 express-server/index.js create mode 100644 express-server/node_modules/.bin/certpem create mode 100644 express-server/node_modules/.bin/mkdirp create mode 100644 express-server/node_modules/.bin/rsa-keygen-js create mode 100644 express-server/node_modules/@coolaj86/urequest/LICENSE create mode 100644 express-server/node_modules/@coolaj86/urequest/README.md create mode 100644 express-server/node_modules/@coolaj86/urequest/index.js create mode 100644 express-server/node_modules/@coolaj86/urequest/package.json create mode 100644 express-server/node_modules/acme-v2/.jshintrc create mode 100644 express-server/node_modules/acme-v2/LICENSE create mode 100644 express-server/node_modules/acme-v2/README.md create mode 100644 express-server/node_modules/acme-v2/compat.js create mode 100644 express-server/node_modules/acme-v2/examples/cli.js create mode 100644 express-server/node_modules/acme-v2/examples/genkeypair.js create mode 100644 express-server/node_modules/acme-v2/examples/http-server.js create mode 100644 express-server/node_modules/acme-v2/examples/https-server.js create mode 100644 express-server/node_modules/acme-v2/node.js create mode 100644 express-server/node_modules/acme-v2/package.json create mode 100644 express-server/node_modules/acme-v2/tests/cb.js create mode 100644 express-server/node_modules/acme-v2/tests/compat.js create mode 100644 express-server/node_modules/acme-v2/tests/fullchain-formats.js create mode 100644 express-server/node_modules/acme-v2/tests/promise.js create mode 100644 express-server/node_modules/acme/LICENSE create mode 100644 express-server/node_modules/acme/README.md create mode 100644 express-server/node_modules/acme/examples/cli.js create mode 100644 express-server/node_modules/acme/examples/genkeypair.js create mode 100644 express-server/node_modules/acme/examples/http-server.js create mode 100644 express-server/node_modules/acme/examples/https-server.js create mode 100644 express-server/node_modules/acme/node.js create mode 100644 express-server/node_modules/acme/package.json create mode 100644 express-server/node_modules/acme/tests/promise.js create mode 100644 express-server/node_modules/asn1js/.gitattributes create mode 100644 express-server/node_modules/asn1js/.npmignore create mode 100644 express-server/node_modules/asn1js/CNAME create mode 100644 express-server/node_modules/asn1js/LICENSE create mode 100644 express-server/node_modules/asn1js/README.md create mode 100644 express-server/node_modules/asn1js/examples/ASN.1 usage/asn1_usage.js create mode 100644 express-server/node_modules/asn1js/org/pkijs/asn1.js create mode 100644 express-server/node_modules/asn1js/org/pkijs/common.js create mode 100644 express-server/node_modules/asn1js/package.json create mode 100644 express-server/node_modules/async-limiter/.travis.yml create mode 100644 express-server/node_modules/async-limiter/LICENSE create mode 100644 express-server/node_modules/async-limiter/coverage/coverage.json create mode 100644 express-server/node_modules/async-limiter/coverage/lcov-report/async-throttle/index.html create mode 100644 express-server/node_modules/async-limiter/coverage/lcov-report/async-throttle/index.js.html create mode 100644 express-server/node_modules/async-limiter/coverage/lcov-report/base.css create mode 100644 express-server/node_modules/async-limiter/coverage/lcov-report/index.html create mode 100644 express-server/node_modules/async-limiter/coverage/lcov-report/prettify.css create mode 100644 express-server/node_modules/async-limiter/coverage/lcov-report/prettify.js create mode 100644 express-server/node_modules/async-limiter/coverage/lcov-report/sort-arrow-sprite.png create mode 100644 express-server/node_modules/async-limiter/coverage/lcov-report/sorter.js create mode 100644 express-server/node_modules/async-limiter/coverage/lcov.info create mode 100644 express-server/node_modules/async-limiter/index.js create mode 100644 express-server/node_modules/async-limiter/package.json create mode 100644 express-server/node_modules/async-limiter/readme.md create mode 100644 express-server/node_modules/batch/.npmignore create mode 100644 express-server/node_modules/batch/History.md create mode 100644 express-server/node_modules/batch/LICENSE create mode 100644 express-server/node_modules/batch/Makefile create mode 100644 express-server/node_modules/batch/Readme.md create mode 100644 express-server/node_modules/batch/component.json create mode 100644 express-server/node_modules/batch/index.js create mode 100644 express-server/node_modules/batch/package.json create mode 100644 express-server/node_modules/bindings/README.md create mode 100644 express-server/node_modules/bindings/bindings.js create mode 100644 express-server/node_modules/bindings/package.json create mode 100644 express-server/node_modules/bluebird/LICENSE create mode 100644 express-server/node_modules/bluebird/README.md create mode 100644 express-server/node_modules/bluebird/changelog.md create mode 100644 express-server/node_modules/bluebird/js/browser/bluebird.core.js create mode 100644 express-server/node_modules/bluebird/js/browser/bluebird.core.min.js create mode 100644 express-server/node_modules/bluebird/js/browser/bluebird.js create mode 100644 express-server/node_modules/bluebird/js/browser/bluebird.min.js create mode 100644 express-server/node_modules/bluebird/js/release/any.js create mode 100644 express-server/node_modules/bluebird/js/release/assert.js create mode 100644 express-server/node_modules/bluebird/js/release/async.js create mode 100644 express-server/node_modules/bluebird/js/release/bind.js create mode 100644 express-server/node_modules/bluebird/js/release/bluebird.js create mode 100644 express-server/node_modules/bluebird/js/release/call_get.js create mode 100644 express-server/node_modules/bluebird/js/release/cancel.js create mode 100644 express-server/node_modules/bluebird/js/release/catch_filter.js create mode 100644 express-server/node_modules/bluebird/js/release/context.js create mode 100644 express-server/node_modules/bluebird/js/release/debuggability.js create mode 100644 express-server/node_modules/bluebird/js/release/direct_resolve.js create mode 100644 express-server/node_modules/bluebird/js/release/each.js create mode 100644 express-server/node_modules/bluebird/js/release/errors.js create mode 100644 express-server/node_modules/bluebird/js/release/es5.js create mode 100644 express-server/node_modules/bluebird/js/release/filter.js create mode 100644 express-server/node_modules/bluebird/js/release/finally.js create mode 100644 express-server/node_modules/bluebird/js/release/generators.js create mode 100644 express-server/node_modules/bluebird/js/release/join.js create mode 100644 express-server/node_modules/bluebird/js/release/map.js create mode 100644 express-server/node_modules/bluebird/js/release/method.js create mode 100644 express-server/node_modules/bluebird/js/release/nodeback.js create mode 100644 express-server/node_modules/bluebird/js/release/nodeify.js create mode 100644 express-server/node_modules/bluebird/js/release/promise.js create mode 100644 express-server/node_modules/bluebird/js/release/promise_array.js create mode 100644 express-server/node_modules/bluebird/js/release/promisify.js create mode 100644 express-server/node_modules/bluebird/js/release/props.js create mode 100644 express-server/node_modules/bluebird/js/release/queue.js create mode 100644 express-server/node_modules/bluebird/js/release/race.js create mode 100644 express-server/node_modules/bluebird/js/release/reduce.js create mode 100644 express-server/node_modules/bluebird/js/release/schedule.js create mode 100644 express-server/node_modules/bluebird/js/release/settle.js create mode 100644 express-server/node_modules/bluebird/js/release/some.js create mode 100644 express-server/node_modules/bluebird/js/release/synchronous_inspection.js create mode 100644 express-server/node_modules/bluebird/js/release/thenables.js create mode 100644 express-server/node_modules/bluebird/js/release/timers.js create mode 100644 express-server/node_modules/bluebird/js/release/using.js create mode 100644 express-server/node_modules/bluebird/js/release/util.js create mode 100644 express-server/node_modules/bluebird/package.json create mode 100644 express-server/node_modules/certpem/LICENSE create mode 100644 express-server/node_modules/certpem/README.md create mode 100644 express-server/node_modules/certpem/bin/certpem.js create mode 100644 express-server/node_modules/certpem/cert.pem create mode 100644 express-server/node_modules/certpem/index.js create mode 100644 express-server/node_modules/certpem/package.json create mode 100644 express-server/node_modules/certpem/test.js create mode 100644 express-server/node_modules/express-basic-auth/.circleci/config.yml create mode 100644 express-server/node_modules/express-basic-auth/README.md create mode 100644 express-server/node_modules/express-basic-auth/example.js create mode 100644 express-server/node_modules/express-basic-auth/express-basic-auth.d.ts create mode 100644 express-server/node_modules/express-basic-auth/index.js create mode 100644 express-server/node_modules/express-basic-auth/package.json create mode 100644 express-server/node_modules/express-basic-auth/test.js create mode 100644 express-server/node_modules/greenlock/LICENSE create mode 100644 express-server/node_modules/greenlock/README.md create mode 100644 express-server/node_modules/greenlock/index.js create mode 100644 express-server/node_modules/greenlock/lib/community.js create mode 100644 express-server/node_modules/greenlock/lib/core.js create mode 100644 express-server/node_modules/greenlock/lib/middleware.js create mode 100644 express-server/node_modules/greenlock/lib/utils.js create mode 100644 express-server/node_modules/greenlock/package.json create mode 100644 express-server/node_modules/ipaddr.js/lib/ipaddr.js.d.ts create mode 100644 express-server/node_modules/le-challenge-fs/.npmignore create mode 100644 express-server/node_modules/le-challenge-fs/LICENSE create mode 100644 express-server/node_modules/le-challenge-fs/README.md create mode 100644 express-server/node_modules/le-challenge-fs/index.js create mode 100644 express-server/node_modules/le-challenge-fs/package.json create mode 100644 express-server/node_modules/le-challenge-fs/test.js create mode 100644 express-server/node_modules/le-sni-auto/LICENSE create mode 100644 express-server/node_modules/le-sni-auto/README.md create mode 100644 express-server/node_modules/le-sni-auto/index.js create mode 100644 express-server/node_modules/le-sni-auto/package.json create mode 100644 express-server/node_modules/le-sni-auto/test.js create mode 100644 express-server/node_modules/le-store-certbot/LICENSE create mode 100644 express-server/node_modules/le-store-certbot/README.md create mode 100644 express-server/node_modules/le-store-certbot/index.js create mode 100644 express-server/node_modules/le-store-certbot/package.json create mode 100644 express-server/node_modules/le-store-certbot/renewal.conf.tpl create mode 100644 express-server/node_modules/minimist/.travis.yml create mode 100644 express-server/node_modules/minimist/LICENSE create mode 100644 express-server/node_modules/minimist/example/parse.js create mode 100644 express-server/node_modules/minimist/index.js create mode 100644 express-server/node_modules/minimist/package.json create mode 100644 express-server/node_modules/minimist/readme.markdown create mode 100644 express-server/node_modules/minimist/test/dash.js create mode 100644 express-server/node_modules/minimist/test/default_bool.js create mode 100644 express-server/node_modules/minimist/test/dotted.js create mode 100644 express-server/node_modules/minimist/test/long.js create mode 100644 express-server/node_modules/minimist/test/parse.js create mode 100644 express-server/node_modules/minimist/test/parse_modified.js create mode 100644 express-server/node_modules/minimist/test/short.js create mode 100644 express-server/node_modules/minimist/test/whitespace.js create mode 100644 express-server/node_modules/mkdirp/.travis.yml create mode 100644 express-server/node_modules/mkdirp/LICENSE create mode 100644 express-server/node_modules/mkdirp/bin/cmd.js create mode 100644 express-server/node_modules/mkdirp/bin/usage.txt create mode 100644 express-server/node_modules/mkdirp/examples/pow.js create mode 100644 express-server/node_modules/mkdirp/index.js create mode 100644 express-server/node_modules/mkdirp/package.json create mode 100644 express-server/node_modules/mkdirp/readme.markdown create mode 100644 express-server/node_modules/mkdirp/test/chmod.js create mode 100644 express-server/node_modules/mkdirp/test/clobber.js create mode 100644 express-server/node_modules/mkdirp/test/mkdirp.js create mode 100644 express-server/node_modules/mkdirp/test/opts_fs.js create mode 100644 express-server/node_modules/mkdirp/test/opts_fs_sync.js create mode 100644 express-server/node_modules/mkdirp/test/perm.js create mode 100644 express-server/node_modules/mkdirp/test/perm_sync.js create mode 100644 express-server/node_modules/mkdirp/test/race.js create mode 100644 express-server/node_modules/mkdirp/test/rel.js create mode 100644 express-server/node_modules/mkdirp/test/return.js create mode 100644 express-server/node_modules/mkdirp/test/return_sync.js create mode 100644 express-server/node_modules/mkdirp/test/root.js create mode 100644 express-server/node_modules/mkdirp/test/sync.js create mode 100644 express-server/node_modules/mkdirp/test/umask.js create mode 100644 express-server/node_modules/mkdirp/test/umask_sync.js create mode 100644 express-server/node_modules/nan/CHANGELOG.md create mode 100644 express-server/node_modules/nan/LICENSE.md create mode 100644 express-server/node_modules/nan/README.md create mode 100644 express-server/node_modules/nan/doc/asyncworker.md create mode 100644 express-server/node_modules/nan/doc/buffers.md create mode 100644 express-server/node_modules/nan/doc/callback.md create mode 100644 express-server/node_modules/nan/doc/converters.md create mode 100644 express-server/node_modules/nan/doc/errors.md create mode 100644 express-server/node_modules/nan/doc/json.md create mode 100644 express-server/node_modules/nan/doc/maybe_types.md create mode 100644 express-server/node_modules/nan/doc/methods.md create mode 100644 express-server/node_modules/nan/doc/new.md create mode 100644 express-server/node_modules/nan/doc/node_misc.md create mode 100644 express-server/node_modules/nan/doc/object_wrappers.md create mode 100644 express-server/node_modules/nan/doc/persistent.md create mode 100644 express-server/node_modules/nan/doc/scopes.md create mode 100644 express-server/node_modules/nan/doc/script.md create mode 100644 express-server/node_modules/nan/doc/string_bytes.md create mode 100644 express-server/node_modules/nan/doc/v8_internals.md create mode 100644 express-server/node_modules/nan/doc/v8_misc.md create mode 100644 express-server/node_modules/nan/include_dirs.js create mode 100644 express-server/node_modules/nan/nan.h create mode 100644 express-server/node_modules/nan/nan_callbacks.h create mode 100644 express-server/node_modules/nan/nan_callbacks_12_inl.h create mode 100644 express-server/node_modules/nan/nan_callbacks_pre_12_inl.h create mode 100644 express-server/node_modules/nan/nan_converters.h create mode 100644 express-server/node_modules/nan/nan_converters_43_inl.h create mode 100644 express-server/node_modules/nan/nan_converters_pre_43_inl.h create mode 100644 express-server/node_modules/nan/nan_define_own_property_helper.h create mode 100644 express-server/node_modules/nan/nan_implementation_12_inl.h create mode 100644 express-server/node_modules/nan/nan_implementation_pre_12_inl.h create mode 100644 express-server/node_modules/nan/nan_json.h create mode 100644 express-server/node_modules/nan/nan_maybe_43_inl.h create mode 100644 express-server/node_modules/nan/nan_maybe_pre_43_inl.h create mode 100644 express-server/node_modules/nan/nan_new.h create mode 100644 express-server/node_modules/nan/nan_object_wrap.h create mode 100644 express-server/node_modules/nan/nan_persistent_12_inl.h create mode 100644 express-server/node_modules/nan/nan_persistent_pre_12_inl.h create mode 100644 express-server/node_modules/nan/nan_private.h create mode 100644 express-server/node_modules/nan/nan_string_bytes.h create mode 100644 express-server/node_modules/nan/nan_typedarray_contents.h create mode 100644 express-server/node_modules/nan/nan_weak.h create mode 100644 express-server/node_modules/nan/package.json create mode 100644 express-server/node_modules/nan/tools/1to2.js create mode 100644 express-server/node_modules/nan/tools/README.md create mode 100644 express-server/node_modules/nan/tools/package.json create mode 100644 express-server/node_modules/pkijs/.gitattributes create mode 100644 express-server/node_modules/pkijs/.npmignore create mode 100644 express-server/node_modules/pkijs/LICENSE create mode 100644 express-server/node_modules/pkijs/README.md create mode 100644 express-server/node_modules/pkijs/org/pkijs/cms_schema.js create mode 100644 express-server/node_modules/pkijs/org/pkijs/cms_simpl.js create mode 100644 express-server/node_modules/pkijs/org/pkijs/common.js create mode 100644 express-server/node_modules/pkijs/org/pkijs/ocsp_tsp_schema.js create mode 100644 express-server/node_modules/pkijs/org/pkijs/ocsp_tsp_simpl.js create mode 100644 express-server/node_modules/pkijs/org/pkijs/pkcs12_schema.js create mode 100644 express-server/node_modules/pkijs/org/pkijs/pkcs12_simpl.js create mode 100644 express-server/node_modules/pkijs/org/pkijs/x509_schema.js create mode 100644 express-server/node_modules/pkijs/org/pkijs/x509_simpl.js create mode 100644 express-server/node_modules/pkijs/package.json create mode 100644 express-server/node_modules/pyconf/LICENSE create mode 100644 express-server/node_modules/pyconf/README.md create mode 100644 express-server/node_modules/pyconf/example.conf create mode 100644 express-server/node_modules/pyconf/index.js create mode 100644 express-server/node_modules/pyconf/package.json create mode 100644 express-server/node_modules/pyconf/test.js create mode 100644 express-server/node_modules/redirect-https/LICENSE create mode 100644 express-server/node_modules/redirect-https/README.md create mode 100644 express-server/node_modules/redirect-https/example.js create mode 100644 express-server/node_modules/redirect-https/index.js create mode 100644 express-server/node_modules/redirect-https/package.json create mode 100644 express-server/node_modules/redirect-https/test.js create mode 100644 express-server/node_modules/rsa-compat/LICENSE create mode 100644 express-server/node_modules/rsa-compat/README.md create mode 100644 express-server/node_modules/rsa-compat/bin/rsa-keygen.js create mode 100644 express-server/node_modules/rsa-compat/fixtures/csr.pem create mode 100644 express-server/node_modules/rsa-compat/fixtures/csr.urlbase64 create mode 100644 express-server/node_modules/rsa-compat/fixtures/privkey.jwk.json create mode 100644 express-server/node_modules/rsa-compat/fixtures/privkey.pkcs1.pem create mode 100644 express-server/node_modules/rsa-compat/fixtures/privkey.pkcs8.pem create mode 100644 express-server/node_modules/rsa-compat/fixtures/signed.jwk.json create mode 100644 express-server/node_modules/rsa-compat/index.js create mode 100644 express-server/node_modules/rsa-compat/lib/generate-privkey-forge.js create mode 100644 express-server/node_modules/rsa-compat/lib/generate-privkey-node.js create mode 100644 express-server/node_modules/rsa-compat/lib/generate-privkey-ursa.js create mode 100644 express-server/node_modules/rsa-compat/lib/generate-privkey.js create mode 100644 express-server/node_modules/rsa-compat/lib/rasha/README.md create mode 100644 express-server/node_modules/rsa-compat/lib/rasha/bin/rasha.js create mode 100644 express-server/node_modules/rsa-compat/lib/rasha/fixtures/privkey-rsa-2048.jwk.json create mode 100644 express-server/node_modules/rsa-compat/lib/rasha/fixtures/privkey-rsa-2048.pkcs1.pem create mode 100644 express-server/node_modules/rsa-compat/lib/rasha/fixtures/privkey-rsa-2048.pkcs8.pem create mode 100644 express-server/node_modules/rsa-compat/lib/rasha/fixtures/pub-rsa-2048.jwk.json create mode 100644 express-server/node_modules/rsa-compat/lib/rasha/fixtures/pub-rsa-2048.pkcs1.pem create mode 100644 express-server/node_modules/rsa-compat/lib/rasha/fixtures/pub-rsa-2048.spki.pem create mode 100644 express-server/node_modules/rsa-compat/lib/rasha/fixtures/pub-rsa-2048.ssh.pub create mode 100644 express-server/node_modules/rsa-compat/lib/rasha/index.js create mode 100644 express-server/node_modules/rsa-compat/lib/rasha/lib/asn1.js create mode 100644 express-server/node_modules/rsa-compat/lib/rasha/lib/encoding.js create mode 100644 express-server/node_modules/rsa-compat/lib/rasha/lib/pem.js create mode 100644 express-server/node_modules/rsa-compat/lib/rasha/lib/rasha.js create mode 100644 express-server/node_modules/rsa-compat/lib/rasha/lib/ssh.js create mode 100644 express-server/node_modules/rsa-compat/lib/rasha/lib/telemetry.js create mode 100644 express-server/node_modules/rsa-compat/lib/rasha/lib/x509.js create mode 100644 express-server/node_modules/rsa-compat/lib/rsa-csr/README.md create mode 100644 express-server/node_modules/rsa-compat/lib/rsa-csr/bin/rsa-csr.js create mode 100644 express-server/node_modules/rsa-compat/lib/rsa-csr/fixtures/example.com-www.csr.pem create mode 100644 express-server/node_modules/rsa-compat/lib/rsa-csr/fixtures/privkey-rsa-2048.jwk.json create mode 100644 express-server/node_modules/rsa-compat/lib/rsa-csr/fixtures/privkey-rsa-2048.pkcs1.pem create mode 100644 express-server/node_modules/rsa-compat/lib/rsa-csr/fixtures/whatever.net-www-api.csr.pem create mode 100644 express-server/node_modules/rsa-compat/lib/rsa-csr/index.js create mode 100644 express-server/node_modules/rsa-compat/lib/rsa-csr/lib/asn1.js create mode 100644 express-server/node_modules/rsa-compat/lib/rsa-csr/lib/csr.js create mode 100644 express-server/node_modules/rsa-compat/lib/rsa-csr/lib/encoding.js create mode 100644 express-server/node_modules/rsa-compat/lib/rsa-csr/lib/pem.js create mode 100644 express-server/node_modules/rsa-compat/lib/rsa-csr/lib/telemetry.js create mode 100644 express-server/node_modules/rsa-compat/lib/rsa-csr/lib/x509.js create mode 100644 express-server/node_modules/rsa-compat/lib/rsa.js create mode 100644 express-server/node_modules/rsa-compat/lib/telemetry.js create mode 100644 express-server/node_modules/rsa-compat/package.json create mode 100644 express-server/node_modules/rsa-compat/test.sh create mode 100644 express-server/node_modules/rsa-compat/tests/generate-csr.js create mode 100644 express-server/node_modules/rsa-compat/tests/generate-key-new.js create mode 100644 express-server/node_modules/rsa-compat/tests/generate-key.js create mode 100644 express-server/node_modules/rsa-compat/tests/generate-sig.js create mode 100644 express-server/node_modules/rsa-compat/tests/privkey.jwk create mode 100644 express-server/node_modules/rsa-compat/tests/privkey.pem create mode 100644 express-server/node_modules/rsa-compat/tests/reciprocate.js create mode 100644 express-server/node_modules/safe-replace/LICENSE create mode 100644 express-server/node_modules/safe-replace/README.md create mode 100644 express-server/node_modules/safe-replace/index.js create mode 100644 express-server/node_modules/safe-replace/package.json create mode 100644 express-server/node_modules/safe-replace/test.js create mode 100644 express-server/node_modules/serve-index/HISTORY.md create mode 100644 express-server/node_modules/serve-index/LICENSE create mode 100644 express-server/node_modules/serve-index/README.md create mode 100644 express-server/node_modules/serve-index/index.js create mode 100644 express-server/node_modules/serve-index/package.json create mode 100644 express-server/node_modules/serve-index/public/directory.html create mode 100644 express-server/node_modules/serve-index/public/icons/application_xp.png create mode 100644 express-server/node_modules/serve-index/public/icons/application_xp_terminal.png create mode 100644 express-server/node_modules/serve-index/public/icons/box.png create mode 100644 express-server/node_modules/serve-index/public/icons/cd.png create mode 100644 express-server/node_modules/serve-index/public/icons/controller.png create mode 100644 express-server/node_modules/serve-index/public/icons/drive.png create mode 100644 express-server/node_modules/serve-index/public/icons/film.png create mode 100644 express-server/node_modules/serve-index/public/icons/folder.png create mode 100644 express-server/node_modules/serve-index/public/icons/font.png create mode 100644 express-server/node_modules/serve-index/public/icons/image.png create mode 100644 express-server/node_modules/serve-index/public/icons/map.png create mode 100644 express-server/node_modules/serve-index/public/icons/page.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_add.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_attach.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_code.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_copy.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_delete.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_edit.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_error.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_excel.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_find.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_gear.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_go.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_green.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_key.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_lightning.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_link.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_paintbrush.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_paste.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_red.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_refresh.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_save.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_acrobat.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_actionscript.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_add.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_c.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_camera.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_cd.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_code.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_code_red.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_coldfusion.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_compressed.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_copy.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_cplusplus.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_csharp.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_cup.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_database.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_delete.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_dvd.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_edit.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_error.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_excel.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_find.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_flash.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_freehand.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_gear.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_get.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_go.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_h.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_horizontal.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_key.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_lightning.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_link.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_magnify.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_medal.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_office.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_paint.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_paintbrush.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_paste.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_php.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_picture.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_powerpoint.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_put.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_ruby.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_stack.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_star.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_swoosh.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_text.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_text_width.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_tux.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_vector.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_visualstudio.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_width.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_word.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_world.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_wrench.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_white_zip.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_word.png create mode 100644 express-server/node_modules/serve-index/public/icons/page_world.png create mode 100644 express-server/node_modules/serve-index/public/style.css create mode 100644 express-server/node_modules/ursa-optional/.travis.yml create mode 100644 express-server/node_modules/ursa-optional/LICENSE.txt create mode 100644 express-server/node_modules/ursa-optional/README.md create mode 100644 express-server/node_modules/ursa-optional/binding.gyp create mode 100644 express-server/node_modules/ursa-optional/build/Makefile create mode 100644 express-server/node_modules/ursa-optional/build/Release/.deps/Release/obj.target/ursaNative.node.d create mode 100644 express-server/node_modules/ursa-optional/build/Release/.deps/Release/obj.target/ursaNative/src/ursaNative.o.d create mode 100644 express-server/node_modules/ursa-optional/build/Release/.deps/Release/ursaNative.node.d create mode 100644 express-server/node_modules/ursa-optional/build/Release/obj.target/ursaNative.node create mode 100644 express-server/node_modules/ursa-optional/build/Release/obj.target/ursaNative/src/ursaNative.o create mode 100644 express-server/node_modules/ursa-optional/build/Release/ursaNative.node create mode 100644 express-server/node_modules/ursa-optional/build/binding.Makefile create mode 100644 express-server/node_modules/ursa-optional/build/config.gypi create mode 100644 express-server/node_modules/ursa-optional/build/ursaNative.target.mk create mode 100644 express-server/node_modules/ursa-optional/lib/ursa.js create mode 100644 express-server/node_modules/ursa-optional/package.json create mode 100644 express-server/node_modules/ursa-optional/rebuild.js create mode 100644 express-server/node_modules/ursa-optional/src/ursaNative.cc create mode 100644 express-server/node_modules/ursa-optional/src/ursaNative.h create mode 100644 express-server/node_modules/ursa-optional/test/.eslintrc.json create mode 100644 express-server/node_modules/ursa-optional/test/another_zorch.pem create mode 100644 express-server/node_modules/ursa-optional/test/blort-pass.pem create mode 100644 express-server/node_modules/ursa-optional/test/blort.pem create mode 100644 express-server/node_modules/ursa-optional/test/blort.pub create mode 100644 express-server/node_modules/ursa-optional/test/blort.sshpub create mode 100644 express-server/node_modules/ursa-optional/test/fixture.js create mode 100644 express-server/node_modules/ursa-optional/test/native.js create mode 100644 express-server/node_modules/ursa-optional/test/pss_tv.pub create mode 100644 express-server/node_modules/ursa-optional/test/test.js create mode 100644 express-server/node_modules/ursa-optional/test/zorch.pem create mode 100644 express-server/node_modules/ursa-optional/test/zorch.pub create mode 100644 express-server/node_modules/utils-merge/.npmignore create mode 100644 express-server/node_modules/ws/LICENSE create mode 100644 express-server/node_modules/ws/README.md create mode 100644 express-server/node_modules/ws/index.js create mode 100644 express-server/node_modules/ws/lib/buffer-util.js create mode 100644 express-server/node_modules/ws/lib/constants.js create mode 100644 express-server/node_modules/ws/lib/event-target.js create mode 100644 express-server/node_modules/ws/lib/extension.js create mode 100644 express-server/node_modules/ws/lib/permessage-deflate.js create mode 100644 express-server/node_modules/ws/lib/receiver.js create mode 100644 express-server/node_modules/ws/lib/sender.js create mode 100644 express-server/node_modules/ws/lib/validation.js create mode 100644 express-server/node_modules/ws/lib/websocket-server.js create mode 100644 express-server/node_modules/ws/lib/websocket.js create mode 100644 express-server/node_modules/ws/package.json create mode 100644 express-server/test/greenlock.js diff --git a/express-server/LICENSE b/express-server/LICENSE new file mode 100644 index 00000000..b9ef4d36 --- /dev/null +++ b/express-server/LICENSE @@ -0,0 +1,41 @@ +Copyright 2017 AJ ONeal + +This is open source software; you can redistribute it and/or modify it under the +terms of either: + + a) the "MIT License" + b) the "Apache-2.0 License" + +MIT License + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + +Apache-2.0 License Summary + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/express-server/examples/demo.js b/express-server/examples/demo.js new file mode 100644 index 00000000..d9bee690 --- /dev/null +++ b/express-server/examples/demo.js @@ -0,0 +1,75 @@ +'use strict'; + +// npm install spdy@3.x + +//var Greenlock = require('greenlock-express') +var Greenlock = require('../'); + +var greenlock = Greenlock.create({ + + // Let's Encrypt v2 is ACME draft 11 + version: 'draft-11' + +, server: 'https://acme-v02.api.letsencrypt.org/directory' + // Note: If at first you don't succeed, stop and switch to staging + // https://acme-staging-v02.api.letsencrypt.org/directory + + // You MUST change this to a valid email address +, email: 'jon@example.com' + + // You MUST NOT build clients that accept the ToS without asking the user +, agreeTos: true + + // You MUST change these to valid domains + // NOTE: all domains will validated and listed on the certificate +, approvedDomains: [ 'example.com', 'www.example.com' ] + + // You MUST have access to write to directory where certs are saved + // ex: /home/foouser/acme/etc +, configDir: '~/.config/acme/' + + // Get notified of important updates and help me make greenlock better +, communityMember: true + +//, debug: true + +}); + + + +//////////////////////// +// http-01 Challenges // +//////////////////////// + +// http-01 challenge happens over http/1.1, not http2 +var redirectHttps = require('redirect-https')(); +var acmeChallengeHandler = greenlock.middleware(function (req, res) { + res.setHeader('Content-Type', 'text/html; charset=utf-8'); + res.end('

Hello, ⚠️ Insecure World!

Visit Secure Site' + + '' + ); +}); +require('http').createServer(acmeChallengeHandler).listen(80, function () { + console.log("Listening for ACME http-01 challenges on", this.address()); +}); + + + +//////////////////////// +// http2 via SPDY h2 // +//////////////////////// + +// spdy is a drop-in replacement for the https API +var spdyOptions = Object.assign({}, greenlock.tlsOptions); +spdyOptions.spdy = { protocols: [ 'h2', 'http/1.1' ], plain: false }; +var server = require('spdy').createServer(spdyOptions, require('express')().use('/', function (req, res) { + res.setHeader('Content-Type', 'text/html; charset=utf-8'); + res.end('

Hello, 🔐 Secure World!

'); +})); +server.on('error', function (err) { + console.error(err); +}); +server.on('listening', function () { + console.log("Listening for SPDY/http2/https requests on", this.address()); +}); +server.listen(443); diff --git a/express-server/examples/force-renew.js b/express-server/examples/force-renew.js new file mode 100644 index 00000000..8c8f4638 --- /dev/null +++ b/express-server/examples/force-renew.js @@ -0,0 +1,29 @@ +'use strict'; + +//require('greenlock-express') +require('../').create({ + + // Let's Encrypt v2 is ACME draft 11 + version: 'draft-11' + +, server: 'https://acme-v02.api.letsencrypt.org/directory' + // Note: If at first you don't succeed, stop and switch to staging + // https://acme-staging-v02.api.letsencrypt.org/directory + +, email: 'john.doe@example.com' + +, agreeTos: true + +, approvedDomains: [ 'example.com', 'www.example.com' ] + +, app: require('express')().use('/', function (req, res) { + res.end('Hello, World!'); + }) + +, renewWithin: (91 * 24 * 60 * 60 * 1000) +, renewBy: (90 * 24 * 60 * 60 * 1000) + + // Get notified of important updates and help me make greenlock better +, communityMember: true +, debug: true +}).listen(80, 443); diff --git a/express-server/examples/http2.js b/express-server/examples/http2.js new file mode 100644 index 00000000..5b30c65e --- /dev/null +++ b/express-server/examples/http2.js @@ -0,0 +1,74 @@ +'use strict'; + +//var Greenlock = require('greenlock-express') +var Greenlock = require('../'); + +var greenlock = Greenlock.create({ + + // Let's Encrypt v2 is ACME draft 11 + version: 'draft-11' + +, server: 'https://acme-v02.api.letsencrypt.org/directory' + // Note: If at first you don't succeed, stop and switch to staging + // https://acme-staging-v02.api.letsencrypt.org/directory + + // You MUST change this to a valid email address +, email: 'jon@example.com' + + // You MUST NOT build clients that accept the ToS without asking the user +, agreeTos: true + + // You MUST change these to valid domains + // NOTE: all domains will validated and listed on the certificate +, approvedDomains: [ 'example.com', 'www.example.com' ] + + // You MUST have access to write to directory where certs are saved + // ex: /home/foouser/acme/etc +, configDir: '~/.config/acme/' + + // Get notified of important updates and help me make greenlock better +, communityMember: true + +//, debug: true + +}); + + + +//////////////////////// +// http-01 Challenges // +//////////////////////// + +// http-01 challenge happens over http/1.1, not http2 +var redirectHttps = require('redirect-https')(); +var acmeChallengeHandler = greenlock.middleware(redirectHttps); +require('http').createServer(acmeChallengeHandler).listen(80, function () { + console.log("Listening for ACME http-01 challenges on", this.address()); +}); + + + +//////////////////////// +// node.js' http2 api // +//////////////////////// + +// http2 is a new API with which you would use hapi or koa, not express +var server = require('http2').createSecureServer(greenlock.tlsOptions); +server.on('error', function (err) { + console.error(err); +}); +// WARNING: Because the middleware don't handle this API style, +// the Host headers are unmodified and potentially dangerous +// (ex: Host: Robert'); DROP TABLE Students;) +server.on('stream', function (stream, headers) { + console.log(headers); + stream.respond({ + 'content-type': 'text/html' + , ':status': 200 + }); + stream.end('Hello, HTTP2 World!'); +}); +server.on('listening', function () { + console.log("Listening for http2 requests on", this.address()); +}); +server.listen(443); diff --git a/express-server/examples/my-express-app.js b/express-server/examples/my-express-app.js new file mode 100644 index 00000000..04da0987 --- /dev/null +++ b/express-server/examples/my-express-app.js @@ -0,0 +1,15 @@ +'use strict'; + +var express = require('express'); +var app = express(); + +app.use('/', function (req, res) { + res.setHeader('Content-Type', 'text/html; charset=utf-8'); + res.end('Hello, World!\n\n💚 🔒.js'); +}); + +// DO NOT DO app.listen() unless we're testing this directly +if (require.main === module) { app.listen(3000); } + +// Instead do export the app: +module.exports = app; diff --git a/express-server/examples/production.js b/express-server/examples/production.js new file mode 100644 index 00000000..08ee7efc --- /dev/null +++ b/express-server/examples/production.js @@ -0,0 +1,90 @@ +'use strict'; + +// +// My Secure Server +// +//var greenlock = require('greenlock-express') +var greenlock = require('../').create({ + + // Let's Encrypt v2 is ACME draft 11 + // Note: If at first you don't succeed, stop and switch to staging + // https://acme-staging-v02.api.letsencrypt.org/directory + server: 'https://acme-v02.api.letsencrypt.org/directory' +, version: 'draft-11' + // You MUST have write access to save certs +, configDir: '~/.config/acme/' + +// The previous 'simple' example set these values statically, +// but this example uses approveDomains() to set them dynamically +//, email: 'none@see.note.above' +//, agreeTos: false + + // approveDomains is the right place to check a database for + // email addresses with domains and agreements and such +, approveDomains: approveDomains + +, app: require('./my-express-app.js') + + // Get notified of important updates and help me make greenlock better +, communityMember: true + +//, debug: true + +}); + +var server = greenlock.listen(80, 443); + + +// +// My Secure Database Check +// +function approveDomains(opts, certs, cb) { + + // Only one domain is listed with *automatic* registration via SNI + // (it's an array because managed registration allows for multiple domains, + // which was the case in the simple example) + console.log(opts.domains); + + // The domains being approved for the first time are listed in opts.domains + // Certs being renewed are listed in certs.altnames + if (certs) { + opts.domains = [certs.subject].concat(certs.altnames); + } + + fooCheckDb(opts.domains, function (err, agree, email) { + if (err) { cb(err); return; } + + // Services SHOULD automatically accept the ToS and use YOUR email + // Clients MUST NOT accept the ToS without asking the user + opts.agreeTos = agree; + opts.email = email; + + // NOTE: you can also change other options such as `challengeType` and `challenge` + // (this would be helpful if you decided you wanted wildcard support as a domain altname) + // opts.challengeType = 'http-01'; + // opts.challenge = require('le-challenge-fs').create({}); + + cb(null, { options: opts, certs: certs }); + }); +} + + +// +// My User / Domain Database +// +function fooCheckDb(domains, cb) { + // This is an oversimplified example of how we might implement a check in + // our database if we have different rules for different users and domains + var domains = [ 'example.com', 'www.example.com' ]; + var userEmail = 'john.doe@example.com'; + var userAgrees = true; + var passCheck = opts.domains.every(function (domain) { + return -1 !== domains.indexOf(domain); + }); + + if (!passCheck) { + cb(new Error('domain not allowed')); + } else { + cb(null, userAgrees, userEmail); + } +} diff --git a/express-server/examples/quickstart.js b/express-server/examples/quickstart.js new file mode 100644 index 00000000..322f7ecf --- /dev/null +++ b/express-server/examples/quickstart.js @@ -0,0 +1,36 @@ +'use strict'; + +var app = require('../app'); + +//require('greenlock-express') +require('../').create({ + + // Let's Encrypt v2 is ACME draft 11 + version: 'draft-11' + +, server: 'https://acme-v02.api.letsencrypt.org/directory' + // Note: If at first you don't succeed, stop and switch to staging + // https://acme-staging-v02.api.letsencrypt.org/directory + + // You MUST change this to a valid email address +, email: 'lukas.n912@gmail.com' + + // You MUST NOT build clients that accept the ToS without asking the user +, agreeTos: true + + // You MUST change these to valid domains + // NOTE: all domains will validated and listed on the certificate +, approvedDomains: [ 'www.smartshopper.cf', 'smartshopper.cf'] + + // You MUST have access to write to directory where certs are saved + // ex: /home/foouser/acme/etc +, configDir: '~/.config/acme/' + +, app: app + + // Get notified of important updates and help me make greenlock better +, communityMember: true + +//, debug: true + +}).listen(7000, 443); diff --git a/express-server/examples/remote-access.js b/express-server/examples/remote-access.js new file mode 100644 index 00000000..87676d6f --- /dev/null +++ b/express-server/examples/remote-access.js @@ -0,0 +1,95 @@ +'use strict'; + +// +// WARNING: Not for noobs +// Try the simple example first +// + +// +// This demo is used with tunnel-server.js and tunnel-client.js +// + +var email = 'john.doe@gmail.com'; +var domains = [ 'example.com' ]; +var agreeLeTos = true; +//var secret = "My Little Brony"; +var secret = require('crypto').randomBytes(16).toString('hex'); + +require('../').create({ + version: 'draft-11' + +, server: 'https://acme-v02.api.letsencrypt.org/directory' + // Note: If at first you don't succeed, stop and switch to staging + // https://acme-staging-v02.api.letsencrypt.org/directory + +, email: email +, agreeTos: agreeLeTos +, approveDomains: domains +, configDir: '~/.config/acme/' +, app: remoteAccess(secret) + // Get notified of important updates and help me make greenlock better +, communityMember: true +//, debug: true +}).listen(3000, 8443); + + +function remoteAccess(secret) { + var express = require('express'); + var basicAuth = require('express-basic-auth'); + var serveIndex = require('serve-index'); + + var rootIndex = serveIndex('/', { hidden: true, icons: true, view: 'details' }); + var rootFs = express.static('/', { dotfiles: 'allow', redirect: true, index: false }); + + var userIndex = serveIndex(require('os').homedir(), { hidden: true, icons: true, view: 'details' }); + var userFs = express.static(require('os').homedir(), { dotfiles: 'allow', redirect: true, index: false }); + + var app = express(); + var realm = 'Login Required'; + + var myAuth = basicAuth({ + users: { 'root': secret, 'user': secret } + , challenge: true + , realm: realm + , unauthorizedResponse: function (/*req*/) { + return 'Unauthorized Home'; + } + }); + + app.get('/', function (req, res) { + res.setHeader('Content-Type', 'text/html; charset=utf-8'); + res.end( + 'View Files' + + '  |  ' + + 'Logout' + ); + }); + app.use('/logout', function (req, res) { + res.setHeader('Content-Type', 'text/html; charset=utf-8'); + res.setHeader('WWW-Authenticate', 'Basic realm="' + realm + '"'); + res.statusCode = 401; + //res.setHeader('Location', '/'); + res.end('Logged out   |   Home'); + }); + app.use('/browse', myAuth); + app.use('/browse', function (req, res, next) { + if ('root' === req.auth.user) { rootFs(req, res, function () { rootIndex(req, res, next); }); return; } + if ('user' === req.auth.user) { userFs(req, res, function () { userIndex(req, res, next); }); return; } + res.end('Sad Panda'); + }); + + console.log(''); + console.log(''); + console.log('Usernames are\n'); + console.log('\troot'); + console.log('\tuser'); + console.log(''); + console.log('Password (for both) is\n'); + console.log('\t' + secret); + console.log(''); + console.log("Shhhh... It's a secret to everybody!"); + console.log(''); + console.log(''); + + return app; +} diff --git a/express-server/examples/spdy.js b/express-server/examples/spdy.js new file mode 100644 index 00000000..0af24704 --- /dev/null +++ b/express-server/examples/spdy.js @@ -0,0 +1,68 @@ +'use strict'; + +// npm install spdy@3.x + +//var Greenlock = require('greenlock-express') +var Greenlock = require('../'); + +var greenlock = Greenlock.create({ + + // Let's Encrypt v2 is ACME draft 11 + version: 'draft-11' + +, server: 'https://acme-v02.api.letsencrypt.org/directory' + // Note: If at first you don't succeed, stop and switch to staging + // https://acme-staging-v02.api.letsencrypt.org/directory + + // You MUST change this to a valid email address +, email: 'jon@example.com' + + // You MUST NOT build clients that accept the ToS without asking the user +, agreeTos: true + + // You MUST change these to valid domains + // NOTE: all domains will validated and listed on the certificate +, approvedDomains: [ 'example.com', 'www.example.com' ] + + // You MUST have access to write to directory where certs are saved + // ex: /home/foouser/acme/etc +, configDir: '~/.config/acme/' // MUST have write access + + // Get notified of important updates and help me make greenlock better +, communityMember: true + +//, debug: true + +}); + + + +//////////////////////// +// http-01 Challenges // +//////////////////////// + +// http-01 challenge happens over http/1.1, not http2 +var redirectHttps = require('redirect-https')(); +var acmeChallengeHandler = greenlock.middleware(redirectHttps); +require('http').createServer(acmeChallengeHandler).listen(80, function () { + console.log("Listening for ACME http-01 challenges on", this.address()); +}); + + + +//////////////////////// +// http2 via SPDY h2 // +//////////////////////// + +// spdy is a drop-in replacement for the https API +var spdyOptions = Object.assign({}, greenlock.tlsOptions); +spdyOptions.spdy = { protocols: [ 'h2', 'http/1.1' ], plain: false }; +var myApp = require('./my-express-app.js'); +var server = require('spdy').createServer(spdyOptions, myApp); +server.on('error', function (err) { + console.error(err); +}); +server.on('listening', function () { + console.log("Listening for SPDY/http2/https requests on", this.address()); +}); +server.listen(443); diff --git a/express-server/examples/vhost.js b/express-server/examples/vhost.js new file mode 100644 index 00000000..977b7633 --- /dev/null +++ b/express-server/examples/vhost.js @@ -0,0 +1,114 @@ +#!/usr/bin/env node +'use strict'; + +/////////////////// +// vhost example // +/////////////////// + +// +// virtual hosting example +// + +// The prefix where sites go by name. +// For example: whatever.com may live in /srv/www/whatever.com, thus /srv/www is our path +var srv = '/srv/www/'; + +var path = require('path'); +var fs = require('fs'); +var finalhandler = require('finalhandler'); +var serveStatic = require('serve-static'); + +//var glx = require('greenlock-express') +var glx = require('../').create({ + + version: 'draft-11' // Let's Encrypt v2 is ACME draft 11 + +, server: 'https://acme-v02.api.letsencrypt.org/directory' // If at first you don't succeed, stop and switch to staging + // https://acme-staging-v02.api.letsencrypt.org/directory + +, configDir: '~/.config/acme/' // You MUST have access to write to directory where certs + // are saved. ex: /home/foouser/.config/acme + +, approveDomains: myApproveDomains // Greenlock's wraps around tls.SNICallback. Check the + // domain name here and reject invalid ones + +, app: myVhostApp // Any node-style http app (i.e. express, koa, hapi, rill) + + /* CHANGE TO A VALID EMAIL */ +, email:'jon@example.com' // Email for Let's Encrypt account and Greenlock Security +, agreeTos: true // Accept Let's Encrypt ToS +, communityMember: true // Join Greenlock to get important updates, no spam + +//, debug: true + +}); + +var server = glx.listen(80, 443); +server.on('listening', function () { + console.info(server.type + " listening on", server.address()); +}); + +// [SECURITY] +// Since v2.4.0+ Greenlock proactively protects against +// SQL injection and timing attacks by rejecting invalid domain names, +// but it's up to you to make sure that you accept opts.domain BEFORE +// an attempt is made to issue a certificate for it. +function myApproveDomains(opts, certs, cb) { + + // In this example the filesystem is our "database". + // We check in /srv/www/ for opts.domain (i.e. "example.com") and only proceed if it exists. + console.log(opts.domain); + + // Check that the hosting domain exists on the file system. + var hostdir = path.join(srv, opts.domain); + fs.readdir(hostdir, function (err, nodes) { + var e; + if (err || !nodes) { + e = new Error("rejecting '" + opts.domains[0] + "' because '" + hostdir + "' could not be read"); + console.error(e); + console.error(err); + cb(e); + return; + } + + // You could put a variety of configuration details alongside the vhost folder + // For example, /srv/www/example.com.json could describe the following: + + // If you have multiple domains grouped together, you can list them on the same certificate + // opts.domains = [ 'example.com', 'www.example.com', 'api.example.com', 'sso.example.com' ] + + // You can also change other options on-the-fly + // (approveDomains is called after the in-memory certificates cache is checked, but before any ACME requests) + + // opts.email = "jon@example.com" + // opts.agreeTos = true; + // opts.challengeType = 'http-01'; + // opts.challenge = require('le-challenge-fs').create({}); + cb(null, { options: opts, certs: certs }); + }); + +} + +// [SECURITY] +// Since v2.4.0+ Greenlock Express will proactively protect against +// SQL injection and timing attacks by rejecting invalid domain names +// in Host headers. +// It will also make them lowercase and protect against "domain fronting". +// However, it's up to you to make sure you actually have a domain to serve :) +var servers = {}; +function myVhostApp(req, res) { + var hostname = req.headers.host; + var srvpath = path.join(srv, hostname); + console.log('vhost for', req.headers.host); + + if (!servers[hostname]) { + try { + fs.accessSync(srvpath); + servers[hostname] = serveStatic(srvpath, { redirect: true }); + } catch(e) { + finalhandler(req, res); + } + } + + servers[hostname](req, res, finalhandler(req, res)); +} diff --git a/express-server/examples/websockets.js b/express-server/examples/websockets.js new file mode 100644 index 00000000..54a69da3 --- /dev/null +++ b/express-server/examples/websockets.js @@ -0,0 +1,40 @@ +'use strict'; + + +//////////////////////// +// Greenlock Setup // +//////////////////////// + +//var Greenlock = require('greenlock-express'); +var Greenlock = require('../'); +var greenlock = Greenlock.create({ + + // Let's Encrypt v2 is ACME draft 11 + // Note: If at first you don't succeed, stop and switch to staging + // https://acme-staging-v02.api.letsencrypt.org/directory + server: 'https://acme-v02.api.letsencrypt.org/directory' +, version: 'draft-11' +, configDir: '~/.config/acme/' +, app: require('./my-express-app.js') + + // You MUST change these to a valid email and domains +, email: 'john.doe@example.com' +, approvedDomains: [ 'example.com', 'www.example.com' ] +, agreeTos: true + + // Get notified of important updates and help me make greenlock better +, communityMember: true +, telemetry: true +//, debug: true +}); + +var server = greenlock.listen(80, 443); + +var WebSocket = require('ws'); +var ws = new WebSocket.Server({ server: server }); +ws.on('connection', function (ws, req) { + // inspect req.headers.authorization (or cookies) for session info + ws.send("[Secure Echo Server] Hello!\nAuth: '" + (req.headers.authorization || 'none') + "'\n" + + "Cookie: '" + (req.headers.cookie || 'none') + "'\n"); + ws.on('message', function (data) { ws.send(data); }); +}); diff --git a/express-server/index.js b/express-server/index.js new file mode 100644 index 00000000..cbab69fe --- /dev/null +++ b/express-server/index.js @@ -0,0 +1,159 @@ +'use strict'; + +var PromiseA; +try { + PromiseA = require('bluebird'); +} catch(e) { + PromiseA = global.Promise; +} + +// opts.approveDomains(options, certs, cb) +module.exports.create = function (opts) { + // accept all defaults for greenlock.challenges, greenlock.store, greenlock.middleware + if (!opts._communityPackage) { + opts._communityPackage = 'greenlock-express.js'; + opts._communityPackageVersion = require('./package.json').version; + } + + function explainError(e) { + console.error('Error:' + e.message); + if ('EACCES' === e.errno) { + console.error("You don't have prmission to access '" + e.address + ":" + e.port + "'."); + console.error("You probably need to use \"sudo\" or \"sudo setcap 'cap_net_bind_service=+ep' $(which node)\""); + return; + } + if ('EADDRINUSE' === e.errno) { + console.error("'" + e.address + ":" + e.port + "' is already being used by some other program."); + console.error("You probably need to stop that program or restart your computer."); + return; + } + console.error(e.code + ": '" + e.address + ":" + e.port + "'"); + } + + function _listen(plainPort, plain) { + if (!plainPort) { plainPort = 80; } + + var parts = String(plainPort).split(':'); + var p = parts.pop(); + var addr = parts.join(':').replace(/^\[/, '').replace(/\]$/, ''); + var args = []; + var httpType; + var server; + var validHttpPort = (parseInt(p, 10) >= 0); + + function tryPlain() { + server = require('http').createServer( + greenlock.middleware.sanitizeHost(greenlock.middleware(require('redirect-https')())) + ); + httpType = 'http'; + } + + function trySecure() { + var https; + try { + https = require('spdy'); + greenlock.tlsOptions.spdy = { protocols: [ 'h2', 'http/1.1' ], plain: false }; + httpType = 'http2 (spdy/h2)'; + } catch(e) { + https = require('https'); + httpType = 'https'; + } + server = https.createServer( + greenlock.tlsOptions + , greenlock.middleware.sanitizeHost(function (req, res) { + try { + greenlock.app(req, res); + } catch(e) { + console.error("[error] [greenlock.app] Your HTTP handler had an uncaught error:"); + console.error(e); + try { + res.statusCode = 500; + res.end("Internal Server Error: [Greenlock] HTTP exception logged for user-provided handler."); + } catch(e) { + // ignore + // (headers may have already been sent, etc) + } + } + }) + ); + server.type = httpType; + } + + if (addr) { args[1] = addr; } + if (!validHttpPort && !/(\/)|(\\\\)/.test(p)) { + console.warn("'" + p + "' doesn't seem to be a valid port number, socket path, or pipe"); + } + if (plain) { tryPlain(); } else { trySecure(); } + + var promise = new PromiseA(function (resolve) { + args[0] = p; + args.push(function () { resolve(server); }); + server.listen.apply(server, args).on('error', function (e) { + if (server.listenerCount('error') < 2) { + console.warn("Did not successfully create http server and bind to port '" + p + "':"); + explainError(e); + process.exit(41); + } + }); + }); + + promise.server = server; + return promise; + } + + // NOTE: 'greenlock' is just 'opts' renamed + var greenlock = require('greenlock').create(opts); + + if (!opts.app) { + opts.app = function (req, res) { + res.end("Hello, World!\nWith Love,\nGreenlock for Express.js"); + }; + } + + opts.listen = function (plainPort, port, fnPlain, fn) { + var promises = []; + var server; + var plainServer; + + // If there is only one handler for the `listening` (i.e. TCP bound) event + // then we want to use it as HTTPS (backwards compat) + if (!fn) { + fn = fnPlain; + fnPlain = null; + } + + promises.push(_listen(plainPort, true)); + promises.push(_listen(port, false)); + + server = promises[1].server; + plainServer = promises[0].server; + + PromiseA.all(promises).then(function () { + // Report plain http status + if ('function' === typeof fnPlain) { + fnPlain.apply(plainServer); + } else if (!fn && !plainServer.listenerCount('listening') && !server.listenerCount('listening')) { + console.info('[:' + (plainServer.address().port || plainServer.address()) + + "] Handling ACME challenges and redirecting to " + server.type); + } + + // Report h2/https status + if ('function' === typeof fn) { + fn.apply(server); + } else if (!server.listenerCount('listening')) { + console.info('[:' + (server.address().port || server.address()) + "] Serving " + server.type); + } + }); + + server.unencrypted = plainServer; + return server; + }; + opts.middleware.acme = function (opts) { + return greenlock.middleware.sanitizeHost(greenlock.middleware(require('redirect-https')(opts))); + }; + opts.middleware.secure = function (app) { + return greenlock.middleware.sanitizeHost(app); + }; + + return greenlock; +}; diff --git a/express-server/node_modules/.bin/certpem b/express-server/node_modules/.bin/certpem new file mode 100644 index 00000000..a5f556fb --- /dev/null +++ b/express-server/node_modules/.bin/certpem @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +'use strict'; + +var certpem = require('../').certpem; +var path = require('path'); +var filepath = (process.cwd() + path.sep + 'cert.pem'); +var debug = false; +var json; +var cert; + +if (/--debug/.test(process.argv[2]) || /--debug/.test(process.argv[3])) { + debug = true; +} +if (/--json/.test(process.argv[2]) || /--json/.test(process.argv[3])) { + json = true; +} +if (process.argv[2] && !/^--/.test(process.argv[2])) { + filepath = process.argv[2]; +} +if (process.argv[3] && !/^--/.test(process.argv[3])) { + filepath = process.argv[3]; +} + +if (filepath.length > 256) { + cert = filepath; +} +else { + cert = require('fs').readFileSync(filepath, 'ascii'); +} + +if (debug) { + console.info(JSON.stringify(certpem.debug(cert), null, ' ')); +} else { + var c = certpem.info(cert); + + if (json) { + console.info(JSON.stringify(c, null, ' ')); + return; + } + + console.info(''); + + console.info('Certificate for', c.subject); + console.info(''); + console.info('Altnames:', c.altnames.join(', ')); + console.info(''); + console.info('Issued at', new Date(c.issuedAt)); + console.info('Expires at', new Date(c.expiresAt)); + + console.info(''); +} diff --git a/express-server/node_modules/.bin/mkdirp b/express-server/node_modules/.bin/mkdirp new file mode 100644 index 00000000..d95de15a --- /dev/null +++ b/express-server/node_modules/.bin/mkdirp @@ -0,0 +1,33 @@ +#!/usr/bin/env node + +var mkdirp = require('../'); +var minimist = require('minimist'); +var fs = require('fs'); + +var argv = minimist(process.argv.slice(2), { + alias: { m: 'mode', h: 'help' }, + string: [ 'mode' ] +}); +if (argv.help) { + fs.createReadStream(__dirname + '/usage.txt').pipe(process.stdout); + return; +} + +var paths = argv._.slice(); +var mode = argv.mode ? parseInt(argv.mode, 8) : undefined; + +(function next () { + if (paths.length === 0) return; + var p = paths.shift(); + + if (mode === undefined) mkdirp(p, cb) + else mkdirp(p, mode, cb) + + function cb (err) { + if (err) { + console.error(err.message); + process.exit(1); + } + else next(); + } +})(); diff --git a/express-server/node_modules/.bin/rsa-keygen-js b/express-server/node_modules/.bin/rsa-keygen-js new file mode 100644 index 00000000..e65176f5 --- /dev/null +++ b/express-server/node_modules/.bin/rsa-keygen-js @@ -0,0 +1,35 @@ +#!/usr/bin/env node +'use strict'; + +var RSA = require('../').RSA; +var path = require('path'); +var fs = require('fs'); + +var bitlen = 2048; +var exp = 65537; +var opts = { public: true, pem: true }; +var cwd = process.cwd(); +var privkeyPath = path.join(cwd, 'privkey.pem'); +var pubkeyPath = path.join(cwd, 'pubkey.pem'); + +if (fs.existsSync(privkeyPath)) { + console.error(privkeyPath, "already exists"); + process.exit(1); +} + +RSA.generateKeypair(bitlen, exp, opts, function (err, keypair) { + console.info(''); + console.info(''); + + fs.writeFileSync(privkeyPath, keypair.privateKeyPem, 'ascii'); + console.info(privkeyPath + ':'); + console.info(''); + console.info(keypair.privateKeyPem); + + console.info(''); + + fs.writeFileSync(pubkeyPath, keypair.publicKeyPem, 'ascii'); + console.info(pubkeyPath + ':'); + console.info(''); + console.info(keypair.publicKeyPem); +}); diff --git a/express-server/node_modules/@coolaj86/urequest/LICENSE b/express-server/node_modules/@coolaj86/urequest/LICENSE new file mode 100644 index 00000000..693448ab --- /dev/null +++ b/express-server/node_modules/@coolaj86/urequest/LICENSE @@ -0,0 +1,41 @@ +Copyright 2018 AJ ONeal + +This is open source software; you can redistribute it and/or modify it under the +terms of either: + + a) the "MIT License" + b) the "Apache-2.0 License" + +MIT License + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + +Apache-2.0 License Summary + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/express-server/node_modules/@coolaj86/urequest/README.md b/express-server/node_modules/@coolaj86/urequest/README.md new file mode 100644 index 00000000..304e6b2d --- /dev/null +++ b/express-server/node_modules/@coolaj86/urequest/README.md @@ -0,0 +1,339 @@ +# µRequest - Minimalist HTTP client + +A lightweight alternative to (and drop-in replacement for) request. + +Written from scratch. + +## Super simple to use + +µRequest is designed to be a drop-in replacement for request. It supports HTTPS and follows redirects by default. + +```bash +npm install --save @coolaj86/urequest +``` + +```js +var request = require('@coolaj86/urequest'); +request('http://www.google.com', function (error, response, body) { + console.log('error:', error); // Print the error if one occurred + console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received + console.log('body:', body); // Print the HTML for the Google homepage. +}); +``` + +## Table of contents + +- [Forms](#forms) +- [HTTP Authentication](#http-authentication) +- [Custom HTTP Headers](#custom-http-headers) +- [Unix Domain Sockets](#unix-domain-sockets) +- [**All Available Options**](#requestoptions-callback) + +## Forms + +`urequest` supports `application/x-www-form-urlencoded` and `multipart/form-data` form uploads. + + +#### application/x-www-form-urlencoded (URL-Encoded Forms) + +URL-encoded forms are simple. + +```js +request.post('http://service.com/upload', {form:{key:'value'}}) +// or +request.post({url:'http://service.com/upload', form: {key:'value'}}, function(err,httpResponse,body){ /* ... */ }) +``` + + + +#### multipart/form-data (Multipart Form Uploads) + +For `multipart/form-data` we use the [form-data](https://github.com/form-data/form-data) library by [@felixge](https://github.com/felixge). For the most cases, you can pass your upload form data via the `formData` option. + + +```js +var formData = { + // Pass a simple key-value pair + my_field: 'my_value', + // Pass data via Buffers + my_buffer: Buffer.from([1, 2, 3]), + // Pass data via Streams + my_file: fs.createReadStream(__dirname + '/unicycle.jpg'), + // Pass multiple values /w an Array + attachments: [ + fs.createReadStream(__dirname + '/attachment1.jpg'), + fs.createReadStream(__dirname + '/attachment2.jpg') + ], + // Pass optional meta-data with an 'options' object with style: {value: DATA, options: OPTIONS} + // Use case: for some types of streams, you'll need to provide "file"-related information manually. + // See the `form-data` README for more information about options: https://github.com/form-data/form-data + custom_file: { + value: fs.createReadStream('/dev/urandom'), + options: { + filename: 'topsecret.jpg', + contentType: 'image/jpeg' + } + } +}; +request.post({url:'http://service.com/upload', formData: formData}, function optionalCallback(err, httpResponse, body) { + if (err) { + return console.error('upload failed:', err); + } + console.log('Upload successful! Server responded with:', body); +}); +``` + + +See the [form-data README](https://github.com/form-data/form-data) for more information & examples. + +--- + +## HTTP Authentication + + +```js +request.get('http://some.server.com/', { + 'auth': { + 'user': 'username', + 'pass': 'password', + 'sendImmediately': false + } +}); +// or +request.get('http://some.server.com/', { + 'auth': { + 'bearer': 'bearerToken' + } +}); +``` + +If passed as an option, `auth` should be a hash containing values: + +- `user` || `username` +- `pass` || `password` +- `bearer` (optional) + + + +Note that you can also specify basic authentication using the URL itself, as +detailed in [RFC 1738](http://www.ietf.org/rfc/rfc1738.txt). Simply pass the +`user:password` before the host with an `@` sign: + +```js +var username = 'username', + password = 'password', + url = 'http://' + username + ':' + password + '@some.server.com'; + +request({url: url}, function (error, response, body) { + // Do more stuff with 'body' here +}); +``` + + + +Bearer authentication is supported, and is activated when the `bearer` value is +available. The value may be either a `String` or a `Function` returning a +`String`. Using a function to supply the bearer token is particularly useful if +used in conjunction with `defaults` to allow a single function to supply the +last known token at the time of sending a request, or to compute one on the fly. + +[back to top](#table-of-contents) + +--- + +## Custom HTTP Headers + +HTTP Headers, such as `User-Agent`, can be set in the `options` object. +In the example below, we call the github API to find out the number +of stars and forks for the request repository. This requires a +custom `User-Agent` header as well as https. + +```js +var request = require('request'); + +var options = { + url: 'https://api.github.com/repos/request/request', + headers: { + 'User-Agent': 'request' + } +}; + +function callback(error, response, body) { + if (!error && response.statusCode == 200) { + var info = JSON.parse(body); + console.log(info.stargazers_count + " Stars"); + console.log(info.forks_count + " Forks"); + } +} + +request(options, callback); +``` + +[back to top](#table-of-contents) + +--- + +## UNIX Domain Sockets + +`urequest` supports making requests to [UNIX Domain Sockets](https://en.wikipedia.org/wiki/Unix_domain_socket). To make one, use the following URL scheme: + +```js +/* Pattern */ 'http://unix:SOCKET:PATH' +/* Example */ request.get('http://unix:/absolute/path/to/unix.socket:/request/path') +``` + +Note: The `SOCKET` path is assumed to be absolute to the root of the host file system. + +[back to top](#table-of-contents) + +--- + +## request(options, callback) + +The first argument can be either a `url` or an `options` object. The only required option is `uri`; all others are optional. + +- `uri` || `url` - fully qualified uri or a parsed url object from `url.parse()` +- `method` - http method (default: `"GET"`) +- `headers` - http headers (default: `{}`) + + + +--- + +- `body` - entity body for PATCH, POST and PUT requests. Must be a `Buffer`, `String` or `ReadStream`. If `json` is `true`, then `body` must be a JSON-serializable object. +- `json` - sets `body` to JSON representation of value and adds `Content-type: application/json` header. Additionally, parses the response body as JSON. + + + +--- + +- `followRedirect` - follow HTTP 3xx responses as redirects (default: `true`). This property can also be implemented as function which gets `response` object as a single argument and should return `true` if redirects should continue or `false` otherwise. +- `followAllRedirects` - follow non-GET HTTP 3xx responses as redirects (default: `false`) +- `followOriginalHttpMethod` - by default we redirect to HTTP method GET. you can enable this property to redirect to the original HTTP method (default: `false`) +- `maxRedirects` - the maximum number of redirects to follow (default: `10`) +- `removeRefererHeader` - removes the referer header when a redirect happens (default: `false`). **Note:** if true, referer header set in the initial request is preserved during redirect chain. + +--- + +- `encoding` - encoding to be used on `setEncoding` of response data. If `null`, the `body` is returned as a `Buffer`. Anything else **(including the default value of `undefined`)** will be passed as the [encoding](http://nodejs.org/api/buffer.html#buffer_buffer) parameter to `toString()` (meaning this is effectively `utf8` by default). (**Note:** if you expect binary data, you should set `encoding: null`.) + + + +--- + +## Convenience methods + +There are also shorthand methods for different HTTP METHODs and some other conveniences. + +### request.defaults(options) + +This method **returns a wrapper** around the normal request API that defaults +to whatever options you pass to it. + +**Note:** `request.defaults()` **does not** modify the global request API; +instead, it **returns a wrapper** that has your default settings applied to it. + +**Note:** You can call `.defaults()` on the wrapper that is returned from +`request.defaults` to add/override defaults that were previously defaulted. + +For example: +```js +//requests using baseRequest() will set the 'x-token' header +var baseRequest = request.defaults({ + headers: {'x-token': 'my-token'} +}) + +//requests using specialRequest() will include the 'x-token' header set in +//baseRequest and will also include the 'special' header +var specialRequest = baseRequest.defaults({ + headers: {special: 'special value'} +}) +``` + +### request.METHOD() + +These HTTP method convenience functions act just like `request()` but with a default method already set for you: + +- *request.get()*: Defaults to `method: "GET"`. +- *request.post()*: Defaults to `method: "POST"`. +- *request.put()*: Defaults to `method: "PUT"`. +- *request.patch()*: Defaults to `method: "PATCH"`. +- *request.del() / request.delete()*: Defaults to `method: "DELETE"`. +- *request.head()*: Defaults to `method: "HEAD"`. +- *request.options()*: Defaults to `method: "OPTIONS"`. + +--- + +## Debugging + +There are at least two ways to debug the operation of `request`: + +1. Launch the node process like `NODE_DEBUG=urequest node script.js` + (`lib,request,otherlib` works too). + +2. Set `require('@coolaj86/urequest').debug = true` at any time (this does the same thing + as #1). + + + +[back to top](#table-of-contents) diff --git a/express-server/node_modules/@coolaj86/urequest/index.js b/express-server/node_modules/@coolaj86/urequest/index.js new file mode 100644 index 00000000..c4a71fde --- /dev/null +++ b/express-server/node_modules/@coolaj86/urequest/index.js @@ -0,0 +1,425 @@ +'use strict'; + +var http = require('http'); +var https = require('https'); +var url = require('url'); + +function debug() { + if (module.exports.debug) { + console.log.apply(console, arguments); + } +} + +function mergeOrDelete(defaults, updates) { + Object.keys(defaults).forEach(function (key) { + if (!(key in updates)) { + updates[key] = defaults[key]; + return; + } + + // neither accept the prior default nor define an explicit value + // CRDT probs... + if ('undefined' === typeof updates[key]) { + delete updates[key]; + } else if ('object' === typeof defaults[key] && 'object' === typeof updates[key]) { + updates[key] = mergeOrDelete(defaults[key], updates[key]); + } + }); + + return updates; +} + +// retrieves an existing header, case-sensitive +function getHeaderName(reqOpts, header) { + var headerNames = {}; + Object.keys(reqOpts.headers).forEach(function (casedName) { + headerNames[casedName.toLowerCase()] = casedName; + }); + // returns the key, which in erroneous cases could be an empty string + return headerNames[header.toLowerCase()]; +} +// returns whether or not a header exists, case-insensitive +function hasHeader(reqOpts, header) { + return 'undefined' !== typeof getHeaderName(reqOpts, header); +} + +function toJSONifier(keys) { + + return function () { + var obj = {}; + var me = this; + + keys.forEach(function (key) { + if (me[key] && 'function' === typeof me[key].toJSON) { + obj[key] = me[key].toJSON(); + } else { + obj[key] = me[key]; + } + }); + + return obj; + }; +} + +function setDefaults(defs) { + defs = defs || {}; + + function urequestHelper(opts, cb) { + debug("\n[urequest] processed options:"); + debug(opts); + + function onResponse(resp) { + var followRedirect; + + Object.keys(defs).forEach(function (key) { + if (key in opts && 'undefined' !== typeof opts[key]) { + return; + } + opts[key] = defs[key]; + }); + followRedirect = opts.followRedirect; + + resp.toJSON = toJSONifier([ 'statusCode', 'body', 'headers', 'request' ]); + + resp.request = req; + resp.request.uri = url.parse(opts.url); + //resp.request.method = opts.method; + resp.request.headers = finalOpts.headers; + resp.request.toJSON = toJSONifier([ 'uri', 'method', 'headers' ]); + + if (followRedirect && resp.headers.location && -1 !== [ 301, 302, 307, 308 ].indexOf(resp.statusCode)) { + debug('Following redirect: ' + resp.headers.location); + if ('GET' !== opts.method && !opts.followAllRedirects) { + followRedirect = false; + } + if (opts._redirectCount >= opts.maxRedirects) { + followRedirect = false; + } + if ('function' === opts.followRedirect) { + if (!opts.followRedirect(resp)) { + followRedirect = false; + } + } + if (followRedirect) { + if (!opts.followOriginalHttpMethod) { + opts.method = 'GET'; + opts.body = null; + delete opts.headers[getHeaderName(opts, 'Content-Length')]; + delete opts.headers[getHeaderName(opts, 'Transfer-Encoding')]; + } + if (opts.removeRefererHeader && opts.headers) { + delete opts.headers.referer; + } + // TODO needs baseUrl, maybe test for host / socketPath? + opts.url = resp.headers.location; + opts.uri = url.parse(opts.url); + return urequestHelper(opts, cb); + } + } + if (null === opts.encoding) { + resp._body = []; + } else { + resp.body = ''; + } + resp._bodyLength = 0; + resp.on('data', function (chunk) { + if ('string' === typeof resp.body) { + resp.body += chunk.toString(opts.encoding); + } else { + resp._body.push(chunk); + resp._bodyLength += chunk.length; + } + }); + resp.on('end', function () { + if ('string' !== typeof resp.body) { + if (1 === resp._body.length) { + resp.body = resp._body[0]; + } else { + resp.body = Buffer.concat(resp._body, resp._bodyLength); + } + resp._body = null; + } + if (opts.json && 'string' === typeof resp.body) { + // TODO I would parse based on Content-Type + // but request.js doesn't do that. + try { + resp.body = JSON.parse(resp.body); + } catch(e) { + // ignore + } + } + + debug("\n[urequest] resp.toJSON():"); + debug(resp.toJSON()); + cb(null, resp, resp.body); + }); + } + + var req; + var finalOpts = {}; + var _body; + var MyFormData; + var form; + var formHeaders; + var requester; + + if (opts.body) { + if (true === opts.json) { + _body = JSON.stringify(opts.body); + } else { + _body = opts.body; + } + } else if (opts.json && true !== opts.json) { + _body = JSON.stringify(opts.json); + } else if (opts.form) { + _body = Object.keys(opts.form).filter(function (key) { + if ('undefined' !== typeof opts.form[key]) { + return true; + } + }).map(function (key) { + return encodeURIComponent(key) + '=' + encodeURIComponent(String(opts.form[key])); + }).join('&'); + opts.headers['Content-Type'] = 'application/x-www-form-urlencoded'; + } + if ('string' === typeof _body) { + _body = Buffer.from(_body); + } + + Object.keys(opts.uri).forEach(function (key) { + finalOpts[key] = opts.uri[key]; + }); + finalOpts.method = opts.method; + finalOpts.headers = JSON.parse(JSON.stringify(opts.headers)); + if (_body) { + // Most APIs expect (or require) Content-Length except in the case of multipart uploads + // Transfer-Encoding: Chunked (the default) is generally only well-supported downstream + finalOpts.headers['Content-Length'] = _body.byteLength || _body.length; + } + if (opts.auth) { + // if opts.uri specifies auth it will be parsed by url.parse and passed directly to the http module + if ('string' !== typeof opts.auth) { + opts.auth = (opts.auth.user||opts.auth.username||'') + ':' + (opts.auth.pass||opts.auth.password||''); + } + if ('string' === typeof opts.auth) { + finalOpts.auth = opts.auth; + } + if (false === opts.sendImmediately) { + console.warn("[Warn] setting `sendImmediately: false` is not yet supported. Please open an issue if this is an important feature that you need."); + } + if (opts.bearer) { + // having a shortcut for base64 encoding makes sense, but this? Eh, whatevs... + finalOpts.header.Authorization = 'Bearer: ' + opts.bearer; + } + } + if (opts.formData) { + try { + MyFormData = opts.FormData || require('form-data'); + // potential options https://github.com/felixge/node-combined-stream/blob/master/lib/combined_stream.js#L7-L15 + } catch(e) { + console.error("urequest does not include extra dependencies by default"); + console.error("if you need to use 'form-data' you may install it, like so:"); + console.error(" npm install --save form-data"); + cb(e); + return; + } + try { + form = new MyFormData(); + Object.keys(opts.formData).forEach(function (key) { + function add(key, data, opts) { + if (data.value) { opts = data.options; data = data.value; } + form.append(key, data, opts); + } + if (Array.isArray(opts.formData[key])) { + opts.formData[key].forEach(function (data) { + add(key, data); + }); + } else { + add(key, opts.formData[key]); + } + }); + } catch(e) { + cb(e); + return; + } + formHeaders = form.getHeaders(); + Object.keys(formHeaders).forEach(function (header) { + finalOpts.headers[header] = formHeaders[header]; + }); + } + + // TODO support unix sockets + if ('https:' === finalOpts.protocol) { + // https://nodejs.org/api/https.html#https_https_request_options_callback + debug("\n[urequest] https.request(opts):"); + debug(finalOpts); + requester = https; + } else if ('http:' === finalOpts.protocol) { + // https://nodejs.org/api/http.html#http_http_request_options_callback + debug("\n[urequest] http.request(opts):"); + debug(finalOpts); + requester = http; + } else { + cb(new Error("unknown protocol: '" + opts.uri.protocol + "'")); + return; + } + + if (form) { + debug("\n[urequest] '" + finalOpts.method + "' (request) form"); + debug(formHeaders); + // generally uploads don't use Chunked Encoding (some systems have issues with it) + // and I don't want to do the work to calculate the content-lengths. This seems to work. + req = form.submit(finalOpts, function (err, resp) { + if (err) { cb(err); return; } + onResponse(resp); + resp.resume(); + }); + //req = requester.request(finalOpts, onResponse); + //req.on('error', cb); + //form.pipe(req); + return; + } + + req = requester.request(finalOpts, onResponse); + req.on('error', cb); + + if (_body) { + debug("\n[urequest] '" + finalOpts.method + "' (request) body"); + debug(_body); + // used for chunked encoding + //req.write(_body); + // used for known content-length + req.end(_body); + } else { + req.end(); + } + } + + function parseUrl(str) { + var obj = url.parse(str); + var paths; + if ('unix' !== (obj.hostname||obj.host||'').toLowerCase()) { + return obj; + } + + obj.href = null; + obj.hostname = obj.host = null; + + paths = (obj.pathname||obj.path||'').split(':'); + + obj.socketPath = paths.shift(); + obj.pathname = obj.path = paths.join(':'); + + return obj; + } + + function urequest(opts, cb) { + debug("\n[urequest] received options:"); + debug(opts); + var reqOpts = {}; + // request.js behavior: + // encoding: null + json ? unknown + // json => attempt to parse, fail silently + // encoding => buffer.toString(encoding) + // null === encoding => Buffer.concat(buffers) + if ('string' === typeof opts) { + opts = { url: opts }; + } + + module.exports._keys.forEach(function (key) { + if (key in opts && 'undefined' !== typeof opts[key]) { + reqOpts[key] = opts[key]; + } else if (key in defs) { + reqOpts[key] = defs[key]; + } + }); + + // TODO url.resolve(defs.baseUrl, opts.url); + if ('string' === typeof opts.url || 'string' === typeof opts.uri) { + if ('string' === typeof opts.url) { + reqOpts.url = opts.url; + reqOpts.uri = parseUrl(opts.url); + } else if ('string' === typeof opts.uri) { + reqOpts.url = opts.uri; + reqOpts.uri = parseUrl(opts.uri); + } + } else { + if ('object' === typeof opts.uri) { + reqOpts.url = url.format(opts.uri); + reqOpts.uri = opts.uri; + //reqOpts.uri = url.parse(reqOpts.uri); + } else if ('object' === typeof opts.url) { + reqOpts.url = url.format(opts.url); + reqOpts.uri = opts.url; + //reqOpts.uri = url.parse(reqOpts.url); + } + } + + if (opts.body || 'string' === typeof opts.json || opts.form || opts.formData) { + // TODO this is probably a deviation from request's API + // need to check and probably eliminate it + reqOpts.method = (reqOpts.method || 'POST').toUpperCase(); + } else { + reqOpts.method = (reqOpts.method || 'GET').toUpperCase(); + } + if (!reqOpts.headers) { + reqOpts.headers = {}; + } + + // crazy case for easier testing + if (!hasHeader(reqOpts, 'CoNTeNT-TyPe')) { + if ((true === reqOpts.json && reqOpts.body) + || (true !== reqOpts.json && reqOpts.json)) { + reqOpts.headers['Content-Type'] = 'application/json'; + } + } + + return urequestHelper(reqOpts, cb); + } + + urequest.defaults = function (_defs) { + _defs = mergeOrDelete(defs, _defs); + return setDefaults(_defs); + }; + [ 'get', 'put', 'post', 'patch', 'delete', 'head', 'options' ].forEach(function (method) { + urequest[method] = function (obj) { + if ('string' === typeof obj) { + obj = { url: obj }; + } + obj.method = method.toUpperCase(); + urequest(obj); + }; + }); + urequest.del = urequest.delete; + + return urequest; +} + +var _defaults = { + sendImmediately: true +, method: 'GET' +, headers: {} +, useQuerystring: false +, followRedirect: true +, followAllRedirects: false +, followOriginalHttpMethod: false +, maxRedirects: 10 +, removeRefererHeader: false +//, encoding: undefined +, gzip: false +//, body: undefined +//, json: undefined +}; +module.exports = setDefaults(_defaults); + +module.exports._keys = Object.keys(_defaults).concat([ + 'encoding' +, 'body' +, 'json' +, 'form' +, 'auth' +, 'formData' +, 'FormData' +]); +module.exports.debug = (-1 !== (process.env.NODE_DEBUG||'').split(/\s+/g).indexOf('urequest')); + +debug("DEBUG ON for urequest"); diff --git a/express-server/node_modules/@coolaj86/urequest/package.json b/express-server/node_modules/@coolaj86/urequest/package.json new file mode 100644 index 00000000..902bae88 --- /dev/null +++ b/express-server/node_modules/@coolaj86/urequest/package.json @@ -0,0 +1,90 @@ +{ + "_args": [ + [ + "@coolaj86/urequest@^1.3.6", + "/nodeapps/https-test/greenlock-express.js/node_modules/acme-v2" + ] + ], + "_from": "@coolaj86/urequest@>=1.3.6 <2.0.0", + "_id": "@coolaj86/urequest@1.3.6", + "_inCache": true, + "_installable": true, + "_location": "/@coolaj86/urequest", + "_nodeVersion": "10.6.0", + "_npmOperationalInternal": { + "host": "s3://npm-registry-packages", + "tmp": "tmp/urequest_1.3.6_1531386792567_0.12131716051599817" + }, + "_npmUser": { + "email": "coolaj86@gmail.com", + "name": "coolaj86" + }, + "_npmVersion": "6.1.0", + "_phantomChildren": {}, + "_requested": { + "name": "@coolaj86/urequest", + "raw": "@coolaj86/urequest@^1.3.6", + "rawSpec": "^1.3.6", + "scope": "@coolaj86", + "spec": ">=1.3.6 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/acme-v2" + ], + "_resolved": "https://registry.npmjs.org/@coolaj86/urequest/-/urequest-1.3.6.tgz", + "_shasum": "e962d62000d7786a3920e5ef2c863223353b2e7f", + "_shrinkwrap": null, + "_spec": "@coolaj86/urequest@^1.3.6", + "_where": "/nodeapps/https-test/greenlock-express.js/node_modules/acme-v2", + "author": { + "email": "coolaj86@gmail.com", + "name": "AJ ONeal", + "url": "https://coolaj86.com/" + }, + "dependencies": {}, + "description": "A lightweight drop-in replacement for request", + "devDependencies": {}, + "directories": { + "example": "examples" + }, + "dist": { + "fileCount": 4, + "integrity": "sha512-9rBXLFSb5D19opGeXdD/WuiFJsA4Pk2r8VUGEAeUZUxB1a2zB47K85BKAx3Gy9i4nZwg22ejlJA+q9DVrpQlbA==", + "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbRxuoCRA9TVsSAnZWagAApwoP/1j5hEoPiQ8KUaczLwxA\ndecbvvUHz5ePW/gpccAfZkjlQzJozZx+PUlpJGFE2ees6lmSjtoW3kq8bAQU\n/BOtmSGUy1VLmDsj1hJ2NVRXSxa9B7ujUzfbxUgL8zOe0/c/rnx3/gEsRg0I\nML9GyogGHbvVx86EdFLYvAo5Gnc6xpFnid/a5Dr7F60C4ACUakDt1jyeEVug\n6CqgU3I/Zw+7NUKWJebPvo7XxLuHi39ScrSMCNRfwEpXWTMpNW+Doz/2PTxv\nTuCXxktRyOjV6tGTv/aMaNqVVdkm2KQEmFfnukrspzEmopmovBMoIhalE0c9\nRwkuGANODSa6Fy6Fu1wU/RbNwgllTxHp+jYFKstenSw8b8/BOqz4P5kWHIAU\nZTd0vLXzY6yTWX7kPEMmq1wt3ydQmckcUzh3+3jIQSjoVZ2aNL+4y1ng/42P\nxQBktUzEUEawl2vSupTN7W6oFcTRHlQxbtQezZjeT5wyz5HWQF7j9s7JQIOO\nnha56Z22hQrmvkXqzDv9cOD3d/lWVWVYOx/PEEVyQVb+ITf21jWLpYu6XCUO\n5LwfK4c+bwJIjyB9I7cYUvxEPhDoXgS0/mft3jqo/WjS+zAOGQA2896PCCrf\n709nMBUAO1cmO2RXpJVU3iqXsfaT5F1IUJl7P0Wgo3bG0ZlCKJ+89z8WPY+h\nyhQm\r\n=ibEw\r\n-----END PGP SIGNATURE-----\r\n", + "shasum": "e962d62000d7786a3920e5ef2c863223353b2e7f", + "tarball": "https://registry.npmjs.org/@coolaj86/urequest/-/urequest-1.3.6.tgz", + "unpackedSize": 28820 + }, + "files": [ + "lib" + ], + "gitHead": "49daa68225e6f53685125ef9ccd0183221ed1b68", + "keywords": [ + "alternative", + "call", + "http", + "https", + "lightweight", + "request" + ], + "license": "(MIT OR Apache-2.0)", + "main": "index.js", + "maintainers": [ + { + "name": "coolaj86", + "email": "coolaj86@gmail.com" + } + ], + "name": "@coolaj86/urequest", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "https://git.ppl.family/ppl/urequest.js.git" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "version": "1.3.6" +} diff --git a/express-server/node_modules/acme-v2/.jshintrc b/express-server/node_modules/acme-v2/.jshintrc new file mode 100644 index 00000000..0bcd7880 --- /dev/null +++ b/express-server/node_modules/acme-v2/.jshintrc @@ -0,0 +1,18 @@ +{ "node": true +, "browser": true +, "jquery": true +, "globals": { "angular": true, "Promise": true } + +, "indent": 2 +, "onevar": true +, "laxcomma": true +, "laxbreak": true +, "curly": true +, "nonbsp": true + +, "eqeqeq": true +, "immed": true +, "undef": true +, "unused": true +, "latedef": true +} \ No newline at end of file diff --git a/express-server/node_modules/acme-v2/LICENSE b/express-server/node_modules/acme-v2/LICENSE new file mode 100644 index 00000000..693448ab --- /dev/null +++ b/express-server/node_modules/acme-v2/LICENSE @@ -0,0 +1,41 @@ +Copyright 2018 AJ ONeal + +This is open source software; you can redistribute it and/or modify it under the +terms of either: + + a) the "MIT License" + b) the "Apache-2.0 License" + +MIT License + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + +Apache-2.0 License Summary + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/express-server/node_modules/acme-v2/README.md b/express-server/node_modules/acme-v2/README.md new file mode 100644 index 00000000..f37bea65 --- /dev/null +++ b/express-server/node_modules/acme-v2/README.md @@ -0,0 +1,221 @@ +| Sponsored by [ppl](https://ppl.family) +| **acme-v2.js** ([npm](https://www.npmjs.com/package/acme-v2)) +| [acme-v2-cli.js](https://git.coolaj86.com/coolaj86/acme-v2-cli.js) +| [greenlock.js](https://git.coolaj86.com/coolaj86/greenlock.js) +| [goldilocks.js](https://git.coolaj86.com/coolaj86/goldilocks.js) +| + +acme-v2.js +========== + +A framework for building Let's Encrypt v2 (ACME draft 11) clients, successor to `le-acme-core.js`. +Built [by request](https://git.coolaj86.com/coolaj86/greenlock.js/issues/5#issuecomment-8). + +## Looking for Quick 'n' Easy™? + +If you're looking for an *ACME-enabled webserver*, try [goldilocks.js](https://git.coolaj86.com/coolaj86/goldilocks.js). +If you're looking to *build a webserver*, try [greenlock.js](https://git.coolaj86.com/coolaj86/greenlock.js). + +* [greenlock.js](https://git.coolaj86.com/coolaj86/greenlock.js) +* [goldilocks.js](https://git.coolaj86.com/coolaj86/goldilocks.js) + +## How to build ACME clients + +As this is intended to build ACME clients, there is not a simple 2-line example. + +I'd recommend first running the example CLI client with a test domain and then investigating the files used for that example: + +```bash +node examples/cli.js +``` + +The example cli has the following prompts: + +``` +What web address(es) would you like to get certificates for? (ex: example.com,*.example.com) +What challenge will you be testing today? http-01 or dns-01? [http-01] +What email should we use? (optional) +What API style would you like to test? v1-compat or promise? [v1-compat] + +Put the string 'mBfh0SqaAV3MOK3B6cAhCbIReAyDuwuxlO1Sl70x6bM.VNAzCR4THe4czVzo9piNn73B1ZXRLaB2CESwJfKkvRM' into a file at 'example.com/.well-known/acme-challenge/mBfh0SqaAV3MOK3B6cAhCbIReAyDuwuxlO1Sl70x6bM' + +echo 'mBfh0SqaAV3MOK3B6cAhCbIReAyDuwuxlO1Sl70x6bM.VNAzCR4THe4czVzo9piNn73B1ZXRLaB2CESwJfKkvRM' > 'example.com/.well-known/acme-challenge/mBfh0SqaAV3MOK3B6cAhCbIReAyDuwuxlO1Sl70x6bM' + +Then hit the 'any' key to continue... +``` + +When you've completed the challenge you can hit a key to continue the process. + +If you place the certificate you receive back in `tests/fullchain.pem` +you can then test it with `examples/https-server.js`. + +``` +examples/cli.js +examples/genkeypair.js +tests/compat.js +examples/https-server.js +examples/http-server.js +``` + +## Let's Encrypt Directory URLs + +``` +# Production URL +https://acme-v02.api.letsencrypt.org/directory +``` + +``` +# Staging URL +https://acme-staging-v02.api.letsencrypt.org/directory +``` + +## Two API versions, Two Implementations + +This library (acme-v2.js) supports ACME [*draft 11*](https://tools.ietf.org/html/draft-ietf-acme-acme-11), +otherwise known as Let's Encrypt v2 (or v02). + + * ACME draft 11 + * Let's Encrypt v2 + * Let's Encrypt v02 + +The predecessor (le-acme-core) supports Let's Encrypt v1 (or v01), which was a +[hodge-podge of various drafts](https://github.com/letsencrypt/boulder/blob/master/docs/acme-divergences.md) +of the ACME spec early on. + + * ACME early draft + * Let's Encrypt v1 + * Let's Encrypt v01 + +This library maintains compatibility with le-acme-core so that it can be used as a **drop-in replacement** +and requires **no changes to existing code**, +but also provides an updated API more congruent with draft 11. + +## le-acme-core-compatible API (recommended) + +Status: Stable, Locked, Bugfix-only + +See Full Documentation at + +``` +var RSA = require('rsa-compat').RSA; +var acme = require('acme-v2/compat.js').ACME.create({ RSA: RSA }); + +// +// Use exactly the same as le-acme-core +// +``` + +## Promise API (dev) + +Status: Almost stable, but **not semver locked** + +This API is a simple evolution of le-acme-core, +but tries to provide a better mapping to the new draft 11 APIs. + +``` +// Create Instance (Dependency Injection) +var ACME = require('acme-v2').ACME.create({ + RSA: require('rsa-compat').RSA + + // other overrides +, request: require('request') +, promisify: require('util').promisify + + // used for constructing user-agent +, os: require('os') +, process: require('process') + + // used for overriding the default user-agent +, userAgent: 'My custom UA String' +, getUserAgentString: function (deps) { return 'My custom UA String'; } + + + // don't try to validate challenges locally +, skipChallengeTest: false + // ask if the certificate can be issued up to 10 times before failing +, retryPoll: 8 + // ask if the certificate has been validated up to 6 times before cancelling +, retryPending: 4 + // Wait 1000ms between retries +, retryInterval: 1000 + // Wait 10,000ms after deauthorizing a challenge before retrying +, deauthWait: 10 * 1000 +}); + + +// Discover Directory URLs +ACME.init(acmeDirectoryUrl) // returns Promise + + +// Accounts +ACME.accounts.create(options) // returns Promise registration data + + { email: '' // valid email (server checks MX records) + , accountKeypair: { // privateKeyPem or privateKeyJwt + privateKeyPem: '' + } + , agreeToTerms: fn (tosUrl) {} // returns Promise with tosUrl + } + + +// Registration +ACME.certificates.create(options) // returns Promise + + { newAuthzUrl: '' // specify acmeUrls.newAuthz + , newCertUrl: '' // specify acmeUrls.newCert + + , domainKeypair: { + privateKeyPem: '' + } + , accountKeypair: { + privateKeyPem: '' + } + , domains: [ 'example.com' ] + + , setChallenge: fn (hostname, key, val) // return Promise + , removeChallenge: fn (hostname, key) // return Promise + } +``` + +Helpers & Stuff + +```javascript +// Constants +ACME.challengePrefixes['http-01'] // '/.well-known/acme-challenge' +ACME.challengePrefixes['dns-01'] // '_acme-challenge' +``` + +Changelog +--------- + +* v1.0.5 - cleanup logging +* v1.0.4 - v6- compat use `promisify` from node's util or bluebird +* v1.0.3 - documentation cleanup +* v1.0.2 + * use `options.contact` to provide raw contact array + * made `options.email` optional + * file cleanup +* v1.0.1 + * Compat API is ready for use + * Eliminate debug logging +* Apr 10, 2018 - tested backwards-compatibility using greenlock.js +* Apr 5, 2018 - export http and dns challenge tests +* Apr 5, 2018 - test http and dns challenges (success and failure) +* Apr 5, 2018 - test subdomains and its wildcard +* Apr 5, 2018 - test two subdomains +* Apr 5, 2018 - test wildcard +* Apr 5, 2018 - completely match api for acme v1 (le-acme-core.js) +* Mar 21, 2018 - *mostly* matches le-acme-core.js API +* Mar 21, 2018 - can now accept values (not hard coded) +* Mar 20, 2018 - SUCCESS - got a test certificate (hard-coded) +* Mar 20, 2018 - download certificate +* Mar 20, 2018 - poll for status +* Mar 20, 2018 - finalize order (submit csr) +* Mar 20, 2018 - generate domain keypair +* Mar 20, 2018 - respond to challenges +* Mar 16, 2018 - get challenges +* Mar 16, 2018 - new order +* Mar 15, 2018 - create account +* Mar 15, 2018 - generate account keypair +* Mar 15, 2018 - get nonce +* Mar 15, 2018 - get directory diff --git a/express-server/node_modules/acme-v2/compat.js b/express-server/node_modules/acme-v2/compat.js new file mode 100644 index 00000000..674c0284 --- /dev/null +++ b/express-server/node_modules/acme-v2/compat.js @@ -0,0 +1,77 @@ +'use strict'; +/* global Promise */ + +var ACME2 = require('./').ACME; + +function resolveFn(cb) { + return function (val) { + // nextTick to get out of Promise chain + process.nextTick(function () { cb(null, val); }); + }; +} +function rejectFn(cb) { + return function (err) { + console.error('[acme-v2] handled(?) rejection as errback:'); + console.error(err.stack); + + // nextTick to get out of Promise chain + process.nextTick(function () { cb(err); }); + + // do not resolve promise further + return new Promise(function () {}); + }; +} + +function create(deps) { + deps.LeCore = {}; + var acme2 = ACME2.create(deps); + acme2.registerNewAccount = function (options, cb) { + acme2.accounts.create(options).then(resolveFn(cb), rejectFn(cb)); + }; + acme2.getCertificate = function (options, cb) { + options.agreeToTerms = options.agreeToTerms || function (tos) { + return Promise.resolve(tos); + }; + acme2.certificates.create(options).then(function (certs) { + var privkeyPem = acme2.RSA.exportPrivatePem(options.domainKeypair); + certs.privkey = privkeyPem; + resolveFn(cb)(certs); + }, rejectFn(cb)); + }; + acme2.getAcmeUrls = function (options, cb) { + acme2.init(options).then(resolveFn(cb), rejectFn(cb)); + }; + acme2.getOptions = function () { + var defs = {}; + + Object.keys(module.exports.defaults).forEach(function (key) { + defs[key] = defs[deps] || module.exports.defaults[key]; + }); + + return defs; + }; + acme2.stagingServerUrl = module.exports.defaults.stagingServerUrl; + acme2.productionServerUrl = module.exports.defaults.productionServerUrl; + acme2.acmeChallengePrefix = module.exports.defaults.acmeChallengePrefix; + return acme2; +} + +module.exports.ACME = { }; +module.exports.defaults = { + productionServerUrl: 'https://acme-v02.api.letsencrypt.org/directory' +, stagingServerUrl: 'https://acme-staging-v02.api.letsencrypt.org/directory' +, knownEndpoints: [ 'keyChange', 'meta', 'newAccount', 'newNonce', 'newOrder', 'revokeCert' ] +, challengeTypes: [ 'http-01', 'dns-01' ] +, challengeType: 'http-01' +//, keyType: 'rsa' // ecdsa +//, keySize: 2048 // 256 +, rsaKeySize: 2048 // 256 +, acmeChallengePrefix: '/.well-known/acme-challenge/' +}; +Object.keys(module.exports.defaults).forEach(function (key) { + module.exports.ACME[key] = module.exports.defaults[key]; +}); +Object.keys(ACME2).forEach(function (key) { + module.exports.ACME[key] = ACME2[key]; +}); +module.exports.ACME.create = create; diff --git a/express-server/node_modules/acme-v2/examples/cli.js b/express-server/node_modules/acme-v2/examples/cli.js new file mode 100644 index 00000000..f26354a5 --- /dev/null +++ b/express-server/node_modules/acme-v2/examples/cli.js @@ -0,0 +1,68 @@ +'use strict'; + +var RSA = require('rsa-compat').RSA; +var readline = require('readline'); +var rl = readline.createInterface({ + input: process.stdin, + output: process.stdout +}); + +require('./genkeypair.js'); + +function getWeb() { + rl.question('What web address(es) would you like to get certificates for? (ex: example.com,*.example.com) ', function (web) { + web = (web||'').trim().split(/,/g); + if (!web[0]) { getWeb(); return; } + + if (web.some(function (w) { return '*' === w[0]; })) { + console.log('Wildcard domains must use dns-01'); + getEmail(web, 'dns-01'); + } else { + getChallengeType(web); + } + }); +} + +function getChallengeType(web) { + rl.question('What challenge will you be testing today? http-01 or dns-01? [http-01] ', function (chType) { + chType = (chType||'').trim(); + if (!chType) { chType = 'http-01'; } + + getEmail(web, chType); + }); +} + +function getEmail(web, chType) { + rl.question('What email should we use? (optional) ', function (email) { + email = (email||'').trim(); + if (!email) { email = null; } + + getApiStyle(web, chType, email); + }); +} + +function getApiStyle(web, chType, email) { + var defaultStyle = 'compat'; + rl.question('What API style would you like to test? v1-compat or promise? [v1-compat] ', function (apiStyle) { + apiStyle = (apiStyle||'').trim(); + if (!apiStyle) { apiStyle = 'v1-compat'; } + + rl.close(); + + var RSA = require('rsa-compat').RSA; + var accountKeypair = RSA.import({ privateKeyPem: require('fs').readFileSync(__dirname + '/../tests/account.privkey.pem') }); + var domainKeypair = RSA.import({ privateKeyPem: require('fs').readFileSync(__dirname + '/../tests/privkey.pem') }); + var directoryUrl = 'https://acme-staging-v02.api.letsencrypt.org/directory'; + + if ('promise' === apiStyle) { + require('../tests/promise.js').run(directoryUrl, RSA, web, chType, email, accountKeypair, domainKeypair); + } else if ('cb' === apiStyle) { + require('../tests/cb.js').run(directoryUrl, RSA, web, chType, email, accountKeypair, domainKeypair); + } else { + if ('v1-compat' !== apiStyle) { console.warn("Didn't understand '" + apiStyle + "', using 'v1-compat' instead..."); } + require('../tests/compat.js').run(directoryUrl, RSA, web, chType, email, accountKeypair, domainKeypair); + } + }); +} + +getWeb(); diff --git a/express-server/node_modules/acme-v2/examples/genkeypair.js b/express-server/node_modules/acme-v2/examples/genkeypair.js new file mode 100644 index 00000000..2c7e3c62 --- /dev/null +++ b/express-server/node_modules/acme-v2/examples/genkeypair.js @@ -0,0 +1,22 @@ +var RSA = require('rsa-compat').RSA; +var fs = require('fs'); + +if (!fs.existsSync(__dirname + '/../tests/account.privkey.pem')) { + RSA.generateKeypair(2048, 65537, {}, function (err, keypair) { + console.log(keypair); + var privkeyPem = RSA.exportPrivatePem(keypair) + console.log(privkeyPem); + + fs.writeFileSync(__dirname + '/../tests/account.privkey.pem', privkeyPem); + }); +} + +if (!fs.existsSync(__dirname + '/../tests/privkey.pem')) { + RSA.generateKeypair(2048, 65537, {}, function (err, keypair) { + console.log(keypair); + var privkeyPem = RSA.exportPrivatePem(keypair) + console.log(privkeyPem); + + fs.writeFileSync(__dirname + '/../tests/privkey.pem', privkeyPem); + }); +} diff --git a/express-server/node_modules/acme-v2/examples/http-server.js b/express-server/node_modules/acme-v2/examples/http-server.js new file mode 100644 index 00000000..4195455d --- /dev/null +++ b/express-server/node_modules/acme-v2/examples/http-server.js @@ -0,0 +1,7 @@ +'use strict'; + +var http = require('http'); +var express = require('express'); +var server = http.createServer(express.static('../tests')).listen(80, function () { + console.log('Listening on', this.address()); +}); diff --git a/express-server/node_modules/acme-v2/examples/https-server.js b/express-server/node_modules/acme-v2/examples/https-server.js new file mode 100644 index 00000000..5dd2c2c9 --- /dev/null +++ b/express-server/node_modules/acme-v2/examples/https-server.js @@ -0,0 +1,11 @@ +'use strict'; + +var https = require('https'); +var server = https.createServer({ + key: require('fs').readFileSync('../tests/privkey.pem') +, cert: require('fs').readFileSync('../tests/fullchain.pem') +}, function (req, res) { + res.end("Hello, World!"); +}).listen(443, function () { + console.log('Listening on', this.address()); +}); diff --git a/express-server/node_modules/acme-v2/node.js b/express-server/node_modules/acme-v2/node.js new file mode 100644 index 00000000..b0b1c8e3 --- /dev/null +++ b/express-server/node_modules/acme-v2/node.js @@ -0,0 +1,719 @@ +/*! + * acme-v2.js + * Copyright(c) 2018 AJ ONeal https://ppl.family + * Apache-2.0 OR MIT (and hence also MPL 2.0) + */ +'use strict'; +/* globals Promise */ + +var ACME = module.exports.ACME = {}; + +ACME.formatPemChain = function formatPemChain(str) { + return str.trim().replace(/[\r\n]+/g, '\n').replace(/\-\n\-/g, '-\n\n-') + '\n'; +}; +ACME.splitPemChain = function splitPemChain(str) { + return str.trim().split(/[\r\n]{2,}/g).map(function (str) { + return str + '\n'; + }); +}; + +ACME.challengePrefixes = { + 'http-01': '/.well-known/acme-challenge' +, 'dns-01': '_acme-challenge' +}; +ACME.challengeTests = { + 'http-01': function (me, auth) { + var url = 'http://' + auth.hostname + ACME.challengePrefixes['http-01'] + '/' + auth.token; + return me._request({ url: url }).then(function (resp) { + var err; + + if (auth.keyAuthorization === resp.body.toString('utf8').trim()) { + return true; + } + + err = new Error( + "Error: Failed HTTP-01 Dry Run.\n" + + "curl '" + url + "' does not return '" + auth.keyAuthorization + "'\n" + + "See https://git.coolaj86.com/coolaj86/acme-v2.js/issues/4" + ); + err.code = 'E_FAIL_DRY_CHALLENGE'; + return Promise.reject(err); + }); + } +, 'dns-01': function (me, auth) { + var hostname = ACME.challengePrefixes['dns-01'] + '.' + auth.hostname; + return me._dig({ + type: 'TXT' + , name: hostname + }).then(function (ans) { + var err; + + if (ans.answer.some(function (txt) { + return auth.dnsAuthorization === txt.data[0]; + })) { + return true; + } + + err = new Error( + "Error: Failed DNS-01 Dry Run.\n" + + "dig TXT '" + hostname + "' does not return '" + auth.dnsAuthorization + "'\n" + + "See https://git.coolaj86.com/coolaj86/acme-v2.js/issues/4" + ); + err.code = 'E_FAIL_DRY_CHALLENGE'; + return Promise.reject(err); + }); + } +}; + +ACME._getUserAgentString = function (deps) { + var uaDefaults = { + pkg: "Greenlock/" + deps.pkg.version + , os: "(" + deps.os.type() + "; " + deps.process.arch + " " + deps.os.platform() + " " + deps.os.release() + ")" + , node: "Node.js/" + deps.process.version + , user: '' + }; + + var userAgent = []; + + //Object.keys(currentUAProps) + Object.keys(uaDefaults).forEach(function (key) { + if (uaDefaults[key]) { + userAgent.push(uaDefaults[key]); + } + }); + + return userAgent.join(' ').trim(); +}; +ACME._directory = function (me) { + return me._request({ url: me.directoryUrl, json: true }); +}; +ACME._getNonce = function (me) { + if (me._nonce) { return new Promise(function (resolve) { resolve(me._nonce); return; }); } + return me._request({ method: 'HEAD', url: me._directoryUrls.newNonce }).then(function (resp) { + me._nonce = resp.toJSON().headers['replay-nonce']; + return me._nonce; + }); +}; +// ACME RFC Section 7.3 Account Creation +/* + { + "protected": base64url({ + "alg": "ES256", + "jwk": {...}, + "nonce": "6S8IqOGY7eL2lsGoTZYifg", + "url": "https://example.com/acme/new-account" + }), + "payload": base64url({ + "termsOfServiceAgreed": true, + "onlyReturnExisting": false, + "contact": [ + "mailto:cert-admin@example.com", + "mailto:admin@example.com" + ] + }), + "signature": "RZPOnYoPs1PhjszF...-nh6X1qtOFPB519I" + } +*/ +ACME._registerAccount = function (me, options) { + if (me.debug) { console.debug('[acme-v2] accounts.create'); } + + return ACME._getNonce(me).then(function () { + return new Promise(function (resolve, reject) { + + function agree(tosUrl) { + var err; + if (me._tos !== tosUrl) { + err = new Error("You must agree to the ToS at '" + me._tos + "'"); + err.code = "E_AGREE_TOS"; + reject(err); + return; + } + + var jwk = me.RSA.exportPublicJwk(options.accountKeypair); + var contact; + if (options.contact) { + contact = options.contact.slice(0); + } else if (options.email) { + contact = [ 'mailto:' + options.email ]; + } + var body = { + termsOfServiceAgreed: tosUrl === me._tos + , onlyReturnExisting: false + , contact: contact + }; + if (options.externalAccount) { + body.externalAccountBinding = me.RSA.signJws( + options.externalAccount.secret + , undefined + , { alg: "HS256" + , kid: options.externalAccount.id + , url: me._directoryUrls.newAccount + } + , Buffer.from(JSON.stringify(jwk)) + ); + } + var payload = JSON.stringify(body); + var jws = me.RSA.signJws( + options.accountKeypair + , undefined + , { nonce: me._nonce + , alg: 'RS256' + , url: me._directoryUrls.newAccount + , jwk: jwk + } + , Buffer.from(payload) + ); + + delete jws.header; + if (me.debug) { console.debug('[acme-v2] accounts.create JSON body:'); } + if (me.debug) { console.debug(jws); } + me._nonce = null; + return me._request({ + method: 'POST' + , url: me._directoryUrls.newAccount + , headers: { 'Content-Type': 'application/jose+json' } + , json: jws + }).then(function (resp) { + var account = resp.body; + + if (2 !== Math.floor(resp.statusCode / 100)) { + throw new Error('account error: ' + JSON.stringify(body)); + } + + me._nonce = resp.toJSON().headers['replay-nonce']; + var location = resp.toJSON().headers.location; + // the account id url + me._kid = location; + if (me.debug) { console.debug('[DEBUG] new account location:'); } + if (me.debug) { console.debug(location); } + if (me.debug) { console.debug(resp.toJSON()); } + + /* + { + contact: ["mailto:jon@example.com"], + orders: "https://some-url", + status: 'valid' + } + */ + if (!account) { account = { _emptyResponse: true, key: {} }; } + // https://git.coolaj86.com/coolaj86/acme-v2.js/issues/8 + if (!account.key) { account.key = {}; } + account.key.kid = me._kid; + return account; + }).then(resolve, reject); + } + + if (me.debug) { console.debug('[acme-v2] agreeToTerms'); } + if (1 === options.agreeToTerms.length) { + // newer promise API + return options.agreeToTerms(me._tos).then(agree, reject); + } + else if (2 === options.agreeToTerms.length) { + // backwards compat cb API + return options.agreeToTerms(me._tos, function (err, tosUrl) { + if (!err) { agree(tosUrl); return; } + reject(err); + }); + } + else { + reject(new Error('agreeToTerms has incorrect function signature.' + + ' Should be fn(tos) { return Promise; }')); + } + }); + }); +}; +/* + POST /acme/new-order HTTP/1.1 + Host: example.com + Content-Type: application/jose+json + + { + "protected": base64url({ + "alg": "ES256", + "kid": "https://example.com/acme/acct/1", + "nonce": "5XJ1L3lEkMG7tR6pA00clA", + "url": "https://example.com/acme/new-order" + }), + "payload": base64url({ + "identifiers": [{"type:"dns","value":"example.com"}], + "notBefore": "2016-01-01T00:00:00Z", + "notAfter": "2016-01-08T00:00:00Z" + }), + "signature": "H6ZXtGjTZyUnPeKn...wEA4TklBdh3e454g" + } +*/ +ACME._getChallenges = function (me, options, auth) { + if (me.debug) { console.debug('\n[DEBUG] getChallenges\n'); } + return me._request({ method: 'GET', url: auth, json: true }).then(function (resp) { + return resp.body; + }); +}; +ACME._wait = function wait(ms) { + return new Promise(function (resolve) { + setTimeout(resolve, (ms || 1100)); + }); +}; +// https://tools.ietf.org/html/draft-ietf-acme-acme-10#section-7.5.1 +ACME._postChallenge = function (me, options, identifier, ch) { + var RETRY_INTERVAL = me.retryInterval || 1000; + var DEAUTH_INTERVAL = me.deauthWait || 10 * 1000; + var MAX_POLL = me.retryPoll || 8; + var MAX_PEND = me.retryPending || 4; + var count = 0; + + var thumbprint = me.RSA.thumbprint(options.accountKeypair); + var keyAuthorization = ch.token + '.' + thumbprint; + // keyAuthorization = token || '.' || base64url(JWK_Thumbprint(accountKey)) + // /.well-known/acme-challenge/:token + var auth = { + identifier: identifier + , hostname: identifier.value + , type: ch.type + , token: ch.token + , thumbprint: thumbprint + , keyAuthorization: keyAuthorization + , dnsAuthorization: me.RSA.utils.toWebsafeBase64( + require('crypto').createHash('sha256').update(keyAuthorization).digest('base64') + ) + }; + + return new Promise(function (resolve, reject) { + /* + POST /acme/authz/1234 HTTP/1.1 + Host: example.com + Content-Type: application/jose+json + + { + "protected": base64url({ + "alg": "ES256", + "kid": "https://example.com/acme/acct/1", + "nonce": "xWCM9lGbIyCgue8di6ueWQ", + "url": "https://example.com/acme/authz/1234" + }), + "payload": base64url({ + "status": "deactivated" + }), + "signature": "srX9Ji7Le9bjszhu...WTFdtujObzMtZcx4" + } + */ + function deactivate() { + var jws = me.RSA.signJws( + options.accountKeypair + , undefined + , { nonce: me._nonce, alg: 'RS256', url: ch.url, kid: me._kid } + , Buffer.from(JSON.stringify({ "status": "deactivated" })) + ); + me._nonce = null; + return me._request({ + method: 'POST' + , url: ch.url + , headers: { 'Content-Type': 'application/jose+json' } + , json: jws + }).then(function (resp) { + if (me.debug) { console.debug('[acme-v2.js] deactivate:'); } + if (me.debug) { console.debug(resp.headers); } + if (me.debug) { console.debug(resp.body); } + if (me.debug) { console.debug(); } + + me._nonce = resp.toJSON().headers['replay-nonce']; + if (me.debug) { console.debug('deactivate challenge: resp.body:'); } + if (me.debug) { console.debug(resp.body); } + return ACME._wait(DEAUTH_INTERVAL); + }); + } + + function pollStatus() { + if (count >= MAX_POLL) { + return Promise.reject(new Error("[acme-v2] stuck in bad pending/processing state")); + } + + count += 1; + + if (me.debug) { console.debug('\n[DEBUG] statusChallenge\n'); } + return me._request({ method: 'GET', url: ch.url, json: true }).then(function (resp) { + + if ('processing' === resp.body.status) { + if (me.debug) { console.debug('poll: again'); } + return ACME._wait(RETRY_INTERVAL).then(pollStatus); + } + + // This state should never occur + if ('pending' === resp.body.status) { + if (count >= MAX_PEND) { + return ACME._wait(RETRY_INTERVAL).then(deactivate).then(testChallenge); + } + if (me.debug) { console.debug('poll: again'); } + return ACME._wait(RETRY_INTERVAL).then(testChallenge); + } + + if ('valid' === resp.body.status) { + if (me.debug) { console.debug('poll: valid'); } + + try { + if (1 === options.removeChallenge.length) { + options.removeChallenge(auth).then(function () {}, function () {}); + } else if (2 === options.removeChallenge.length) { + options.removeChallenge(auth, function (err) { return err; }); + } else { + options.removeChallenge(identifier.value, ch.token, function () {}); + } + } catch(e) {} + return resp.body; + } + + if (!resp.body.status) { + console.error("[acme-v2] (E_STATE_EMPTY) empty challenge state:"); + } + else if ('invalid' === resp.body.status) { + console.error("[acme-v2] (E_STATE_INVALID) challenge state: '" + resp.body.status + "'"); + } + else { + console.error("[acme-v2] (E_STATE_UKN) challenge state: '" + resp.body.status + "'"); + } + + return Promise.reject(new Error("[acme-v2] [error] unacceptable challenge state '" + resp.body.status + "'")); + }); + } + + function respondToChallenge() { + var jws = me.RSA.signJws( + options.accountKeypair + , undefined + , { nonce: me._nonce, alg: 'RS256', url: ch.url, kid: me._kid } + , Buffer.from(JSON.stringify({ })) + ); + me._nonce = null; + return me._request({ + method: 'POST' + , url: ch.url + , headers: { 'Content-Type': 'application/jose+json' } + , json: jws + }).then(function (resp) { + if (me.debug) { console.debug('[acme-v2.js] challenge accepted!'); } + if (me.debug) { console.debug(resp.headers); } + if (me.debug) { console.debug(resp.body); } + if (me.debug) { console.debug(); } + + me._nonce = resp.toJSON().headers['replay-nonce']; + if (me.debug) { console.debug('respond to challenge: resp.body:'); } + if (me.debug) { console.debug(resp.body); } + return ACME._wait(RETRY_INTERVAL).then(pollStatus); + }); + } + + function testChallenge() { + // TODO put check dns / http checks here? + // http-01: GET https://example.org/.well-known/acme-challenge/{{token}} => {{keyAuth}} + // dns-01: TXT _acme-challenge.example.org. => "{{urlSafeBase64(sha256(keyAuth))}}" + + if (me.debug) {console.debug('\n[DEBUG] postChallenge\n'); } + //if (me.debug) console.debug('\n[DEBUG] stop to fix things\n'); return; + + return ACME._wait(RETRY_INTERVAL).then(function () { + if (!me.skipChallengeTest) { + return ACME.challengeTests[ch.type](me, auth); + } + }).then(respondToChallenge); + } + + try { + if (1 === options.setChallenge.length) { + options.setChallenge(auth).then(testChallenge).then(resolve, reject); + } else if (2 === options.setChallenge.length) { + options.setChallenge(auth, function (err) { + if(err) { + reject(err); + } else { + testChallenge().then(resolve, reject); + } + }); + } else { + var challengeCb = function(err) { + if(err) { + reject(err); + } else { + testChallenge().then(resolve, reject); + } + }; + Object.keys(auth).forEach(function (key) { + challengeCb[key] = auth[key]; + }); + options.setChallenge(identifier.value, ch.token, keyAuthorization, challengeCb); + } + } catch(e) { + reject(e); + } + }); +}; +ACME._finalizeOrder = function (me, options, validatedDomains) { + if (me.debug) { console.debug('finalizeOrder:'); } + var csr = me.RSA.generateCsrWeb64(options.domainKeypair, validatedDomains); + var body = { csr: csr }; + var payload = JSON.stringify(body); + + function pollCert() { + var jws = me.RSA.signJws( + options.accountKeypair + , undefined + , { nonce: me._nonce, alg: 'RS256', url: me._finalize, kid: me._kid } + , Buffer.from(payload) + ); + + if (me.debug) { console.debug('finalize:', me._finalize); } + me._nonce = null; + return me._request({ + method: 'POST' + , url: me._finalize + , headers: { 'Content-Type': 'application/jose+json' } + , json: jws + }).then(function (resp) { + // https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.1.3 + // Possible values are: "pending" => ("invalid" || "ready") => "processing" => "valid" + me._nonce = resp.toJSON().headers['replay-nonce']; + + if (me.debug) { console.debug('order finalized: resp.body:'); } + if (me.debug) { console.debug(resp.body); } + + if ('valid' === resp.body.status) { + me._expires = resp.body.expires; + me._certificate = resp.body.certificate; + + return resp.body; // return order + } + + if ('processing' === resp.body.status) { + return ACME._wait().then(pollCert); + } + + if (me.debug) { console.debug("Error: bad status:\n" + JSON.stringify(resp.body, null, 2)); } + + if ('pending' === resp.body.status) { + return Promise.reject(new Error( + "Did not finalize order: status 'pending'." + + " Best guess: You have not accepted at least one challenge for each domain." + "\n\n" + + JSON.stringify(resp.body, null, 2) + )); + } + + if ('invalid' === resp.body.status) { + return Promise.reject(new Error( + "Did not finalize order: status 'invalid'." + + " Best guess: One or more of the domain challenges could not be verified" + + " (or the order was canceled)." + "\n\n" + + JSON.stringify(resp.body, null, 2) + )); + } + + if ('ready' === resp.body.status) { + return Promise.reject(new Error( + "Did not finalize order: status 'ready'." + + " Hmmm... this state shouldn't be possible here. That was the last state." + + " This one should at least be 'processing'." + "\n\n" + + JSON.stringify(resp.body, null, 2) + "\n\n" + + "Please open an issue at https://git.coolaj86.com/coolaj86/acme-v2.js" + )); + } + + return Promise.reject(new Error( + "Didn't finalize order: Unhandled status '" + resp.body.status + "'." + + " This is not one of the known statuses...\n\n" + + JSON.stringify(resp.body, null, 2) + "\n\n" + + "Please open an issue at https://git.coolaj86.com/coolaj86/acme-v2.js" + )); + }); + } + + return pollCert(); +}; +ACME._getCertificate = function (me, options) { + if (me.debug) { console.debug('[acme-v2] DEBUG get cert 1'); } + + if (!options.challengeTypes) { + if (!options.challengeType) { + return Promise.reject(new Error("challenge type must be specified")); + } + options.challengeTypes = [ options.challengeType ]; + } + + if (!me._kid) { + if (options.accountKid) { + me._kid = options.accountKid; + } else { + //return Promise.reject(new Error("must include KeyID")); + return ACME._registerAccount(me, options).then(function () { + return ACME._getCertificate(me, options); + }); + } + } + + if (me.debug) { console.debug('[acme-v2] certificates.create'); } + return ACME._getNonce(me).then(function () { + var body = { + identifiers: options.domains.map(function (hostname) { + return { type: "dns" , value: hostname }; + }) + //, "notBefore": "2016-01-01T00:00:00Z" + //, "notAfter": "2016-01-08T00:00:00Z" + }; + + var payload = JSON.stringify(body); + var jws = me.RSA.signJws( + options.accountKeypair + , undefined + , { nonce: me._nonce, alg: 'RS256', url: me._directoryUrls.newOrder, kid: me._kid } + , Buffer.from(payload) + ); + + if (me.debug) { console.debug('\n[DEBUG] newOrder\n'); } + me._nonce = null; + return me._request({ + method: 'POST' + , url: me._directoryUrls.newOrder + , headers: { 'Content-Type': 'application/jose+json' } + , json: jws + }).then(function (resp) { + me._nonce = resp.toJSON().headers['replay-nonce']; + var location = resp.toJSON().headers.location; + var auths; + if (me.debug) { console.debug(location); } // the account id url + if (me.debug) { console.debug(resp.toJSON()); } + me._authorizations = resp.body.authorizations; + me._order = location; + me._finalize = resp.body.finalize; + //if (me.debug) console.debug('[DEBUG] finalize:', me._finalize); return; + + if (!me._authorizations) { + console.error("[acme-v2.js] authorizations were not fetched:"); + console.error(resp.body); + return Promise.reject(new Error("authorizations were not fetched")); + } + if (me.debug) { console.debug("[acme-v2] POST newOrder has authorizations"); } + + //return resp.body; + auths = me._authorizations.slice(0); + + function next() { + var authUrl = auths.shift(); + if (!authUrl) { return; } + + return ACME._getChallenges(me, options, authUrl).then(function (results) { + // var domain = options.domains[i]; // results.identifier.value + var chType = options.challengeTypes.filter(function (chType) { + return results.challenges.some(function (ch) { + return ch.type === chType; + }); + })[0]; + + var challenge = results.challenges.filter(function (ch) { + if (chType === ch.type) { + return ch; + } + })[0]; + + if (!challenge) { + return Promise.reject(new Error("Server didn't offer any challenge we can handle.")); + } + + return ACME._postChallenge(me, options, results.identifier, challenge); + }).then(function () { + return next(); + }); + } + + return next().then(function () { + if (me.debug) { console.debug("[getCertificate] next.then"); } + var validatedDomains = body.identifiers.map(function (ident) { + return ident.value; + }); + + return ACME._finalizeOrder(me, options, validatedDomains); + }).then(function (order) { + if (me.debug) { console.debug('acme-v2: order was finalized'); } + return me._request({ method: 'GET', url: me._certificate, json: true }).then(function (resp) { + if (me.debug) { console.debug('acme-v2: csr submitted and cert received:'); } + // https://github.com/certbot/certbot/issues/5721 + var certsarr = ACME.splitPemChain(ACME.formatPemChain((resp.body||''))); + // cert, chain, fullchain, privkey, /*TODO, subject, altnames, issuedAt, expiresAt */ + var certs = { + expires: order.expires + , identifiers: order.identifiers + //, authorizations: order.authorizations + , cert: certsarr.shift() + //, privkey: privkeyPem + , chain: certsarr.join('\n') + }; + if (me.debug) { console.debug(certs); } + return certs; + }); + }); + }); + }); +}; + +ACME.create = function create(me) { + if (!me) { me = {}; } + // me.debug = true; + me.challengePrefixes = ACME.challengePrefixes; + me.RSA = me.RSA || require('rsa-compat').RSA; + me.request = me.request || require('@coolaj86/urequest'); + me._dig = function (query) { + // TODO use digd.js + return new Promise(function (resolve, reject) { + var dns = require('dns'); + dns.resolveTxt(query.name, function (err, records) { + if (err) { reject(err); return; } + + resolve({ + answer: records.map(function (rr) { + return { + data: rr + }; + }) + }); + }); + }); + }; + me.promisify = me.promisify || require('util').promisify /*node v8+*/ || require('bluebird').promisify /*node v6*/; + + + if ('function' !== typeof me.getUserAgentString) { + me.pkg = me.pkg || require('./package.json'); + me.os = me.os || require('os'); + me.process = me.process || require('process'); + me.userAgent = ACME._getUserAgentString(me); + } + + function getRequest(opts) { + if (!opts) { opts = {}; } + + return me.request.defaults({ + headers: { + 'User-Agent': opts.userAgent || me.userAgent || me.getUserAgentString(me) + } + }); + } + + if ('function' !== typeof me._request) { + me._request = me.promisify(getRequest({})); + } + + me.init = function (_directoryUrl) { + me.directoryUrl = me.directoryUrl || _directoryUrl; + return ACME._directory(me).then(function (resp) { + me._directoryUrls = resp.body; + me._tos = me._directoryUrls.meta.termsOfService; + return me._directoryUrls; + }); + }; + me.accounts = { + create: function (options) { + return ACME._registerAccount(me, options); + } + }; + me.certificates = { + create: function (options) { + return ACME._getCertificate(me, options); + } + }; + return me; +}; diff --git a/express-server/node_modules/acme-v2/package.json b/express-server/node_modules/acme-v2/package.json new file mode 100644 index 00000000..dc00cdbf --- /dev/null +++ b/express-server/node_modules/acme-v2/package.json @@ -0,0 +1,102 @@ +{ + "_args": [ + [ + "acme-v2@^1.2.0", + "/nodeapps/https-test/greenlock-express.js/node_modules/greenlock" + ] + ], + "_from": "acme-v2@>=1.2.0 <2.0.0", + "_id": "acme-v2@1.2.1", + "_inCache": true, + "_installable": true, + "_location": "/acme-v2", + "_nodeVersion": "10.6.0", + "_npmOperationalInternal": { + "host": "s3://npm-registry-packages", + "tmp": "tmp/acme-v2_1.2.1_1534465950183_0.44524737605461473" + }, + "_npmUser": { + "email": "coolaj86@gmail.com", + "name": "coolaj86" + }, + "_npmVersion": "6.1.0", + "_phantomChildren": {}, + "_requested": { + "name": "acme-v2", + "raw": "acme-v2@^1.2.0", + "rawSpec": "^1.2.0", + "scope": null, + "spec": ">=1.2.0 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/acme", + "/greenlock" + ], + "_resolved": "https://registry.npmjs.org/acme-v2/-/acme-v2-1.2.1.tgz", + "_shasum": "15ef5063b45172e900cfa6f05d608bde590860cc", + "_shrinkwrap": null, + "_spec": "acme-v2@^1.2.0", + "_where": "/nodeapps/https-test/greenlock-express.js/node_modules/greenlock", + "author": { + "email": "coolaj86@gmail.com", + "name": "AJ ONeal", + "url": "https://coolaj86.com/" + }, + "dependencies": { + "@coolaj86/urequest": "^1.3.6", + "rsa-compat": "^1.5.1" + }, + "description": "Free SSL. A framework for building Let's Encrypt v2 clients, and other ACME v2 (draft 11) clients. Successor to le-acme-core.js", + "devDependencies": {}, + "directories": {}, + "dist": { + "fileCount": 14, + "integrity": "sha512-7FRl/vgZpcm7VCOiiAU6ntkclHkkEdCk1uNAkuEA0sZ8R0YX3pBjh066y/QqzEAfmDbbiYr+DYlVhZoHTbmXEQ==", + "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbdhefCRA9TVsSAnZWagAA/XcQAKMNjyd4wCZzld6wlDfC\nr+Mo1CfUugIko2fW6MZ7TGhxPIiVhedC7v/jUxwsZV3oYDdrttTbflkxxoUB\n6ivIdPaTXp/9JXfg0u+2cWrCZufy4d5PQtDDdfrp0GugsUHz/+wrrC2jpCjM\nPRCzGYbwJ7NvEnY5AYU28XI9WL1voCxxxLSjYkPqDjBtGrvcUrghJUsfeqOw\n0gOd3LhSdFunnIV44PTHV4GknAkTUffbpigcfGAtiXfigJ/3xbrjV0k5dpBb\n55q6l+i6Vdvjb8xhYkUO+V7zE/3zZWAaVKHLI+oeVnX/1OrA7tLU05GYj03c\nFaEm57/uS3OQ4atHAy8X6vjXOjuGOoCXpmmNUKZ2whiUHDvsrzEVXhgFAGxb\n9iWghhgwCTn7zPQQKIJdviNEbQXmY+phbG+5mmg2+Z/EHceCi+4t4m/sEoIe\nAzBUTNouU8mMxfWFFDcT8c02LyFanHHsQGC+mtICORZxU8GlCwz7LTU5YLl3\nfkswVaLIYr2Qvlswyf/sJCWCccHgX2j6qlbdNhdV1LBvS1jYmgN83OkmcGTD\nmVyM+lDYqmBkycw29NEAkdZ3LvHsb1t4GOnqDboTOFZll2TSSiaOaLf3yveq\n6beSy/HNuCYzmTxXTeaGPnc1ZwY7iTYZcjTLitzNvKyCwO3Vjiyrtc9Onqx5\n/Yyp\r\n=dHr8\r\n-----END PGP SIGNATURE-----\r\n", + "shasum": "15ef5063b45172e900cfa6f05d608bde590860cc", + "tarball": "https://registry.npmjs.org/acme-v2/-/acme-v2-1.2.1.tgz", + "unpackedSize": 50763 + }, + "gitHead": "ca15b8faf0a11b15d9973a9786c652c117d2547d", + "homepage": "https://git.coolaj86.com/coolaj86/acme-v2.js", + "keywords": [ + "ACME", + "Let's Encrypt", + "automated https", + "draft-11", + "draft-12", + "free ssl", + "letsencrypt", + "tls", + "v02", + "v2" + ], + "license": "(MIT OR Apache-2.0)", + "main": "node.js", + "maintainers": [ + { + "name": "coolaj86", + "email": "coolaj86@gmail.com" + }, + { + "name": "ppl", + "email": "npm@ppl.family" + }, + { + "name": "thejshaver", + "email": "john@jshaver.net" + } + ], + "name": "acme-v2", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "ssh://gitea@git.coolaj86.com:22042/coolaj86/acme-v2.js.git" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "version": "1.2.1" +} diff --git a/express-server/node_modules/acme-v2/tests/cb.js b/express-server/node_modules/acme-v2/tests/cb.js new file mode 100644 index 00000000..550c285e --- /dev/null +++ b/express-server/node_modules/acme-v2/tests/cb.js @@ -0,0 +1,79 @@ +'use strict'; + +module.exports.run = function run(directoryUrl, RSA, web, chType, email, accountKeypair, domainKeypair) { + // [ 'test.ppl.family' ] 'coolaj86@gmail.com''http-01' + var acme2 = require('../').ACME.create({ RSA: RSA }); + acme2.init(directoryUrl).then(function () { + var options = { + agreeToTerms: function (tosUrl, agree) { + agree(null, tosUrl); + } + , setChallenge: function (opts, cb) { + var pathname; + + console.log(""); + console.log('identifier:'); + console.log(opts.identifier); + console.log('hostname:'); + console.log(opts.hostname); + console.log('type:'); + console.log(opts.type); + console.log('token:'); + console.log(opts.token); + console.log('thumbprint:'); + console.log(opts.thumbprint); + console.log('keyAuthorization:'); + console.log(opts.keyAuthorization); + console.log('dnsAuthorization:'); + console.log(opts.dnsAuthorization); + console.log(""); + + if ('http-01' === opts.type) { + pathname = opts.hostname + acme2.challengePrefixes['http-01'] + "/" + opts.token; + console.log("Put the string '" + opts.keyAuthorization + "' into a file at '" + pathname + "'"); + console.log("echo '" + opts.keyAuthorization + "' > '" + pathname + "'"); + } else if ('dns-01' === opts.type) { + pathname = acme2.challengePrefixes['dns-01'] + "." + opts.hostname.replace(/^\*\./, ''); + console.log("Put the string '" + opts.dnsAuthorization + "' into the TXT record '" + pathname + "'"); + console.log("ddig TXT " + pathname + " '" + opts.dnsAuthorization + "'"); + } else { + cb(new Error("[acme-v2] unrecognized challenge type")); + return; + } + console.log("\nThen hit the 'any' key to continue..."); + + function onAny() { + console.log("'any' key was hit"); + process.stdin.pause(); + process.stdin.removeListener('data', onAny); + process.stdin.setRawMode(false); + cb(); + } + + process.stdin.setRawMode(true); + process.stdin.resume(); + process.stdin.on('data', onAny); + } + , removeChallenge: function (opts, cb) { + // hostname, key + console.log('[acme-v2] remove challenge', opts.hostname, opts.keyAuthorization); + setTimeout(cb, 1 * 1000); + } + , challengeType: chType + , email: email + , accountKeypair: accountKeypair + , domainKeypair: domainKeypair + , domains: web + }; + + acme2.accounts.create(options).then(function (account) { + console.log('[acme-v2] account:'); + console.log(account); + + acme2.certificates.create(options).then(function (fullchainPem) { + console.log('[acme-v2] fullchain.pem:'); + console.log(fullchainPem); + }); + }); + }); +}; diff --git a/express-server/node_modules/acme-v2/tests/compat.js b/express-server/node_modules/acme-v2/tests/compat.js new file mode 100644 index 00000000..e643e2e6 --- /dev/null +++ b/express-server/node_modules/acme-v2/tests/compat.js @@ -0,0 +1,68 @@ +'use strict'; + +module.exports.run = function (directoryUrl, RSA, web, chType, email, accountKeypair, domainKeypair) { + console.log('[DEBUG] run', web, chType, email); + + var acme2 = require('../compat.js').ACME.create({ RSA: RSA }); + acme2.getAcmeUrls(acme2.stagingServerUrl, function (err/*, directoryUrls*/) { + if (err) { console.log('err 1'); throw err; } + + var options = { + agreeToTerms: function (tosUrl, agree) { + agree(null, tosUrl); + } + , setChallenge: function (hostname, token, val, cb) { + var pathname; + + if ('http-01' === cb.type) { + pathname = hostname + acme2.acmeChallengePrefix + token; + console.log("Put the string '" + val /*keyAuthorization*/ + "' into a file at '" + pathname + "'"); + console.log("echo '" + val /*keyAuthorization*/ + "' > '" + pathname + "'"); + console.log("\nThen hit the 'any' key to continue..."); + } else if ('dns-01' === cb.type) { + // forwards-backwards compat + pathname = acme2.challengePrefixes['dns-01'] + "." + hostname.replace(/^\*\./, ''); + console.log("Put the string '" + cb.dnsAuthorization + "' into the TXT record '" + pathname + "'"); + console.log("dig TXT " + pathname + " '" + cb.dnsAuthorization + "'"); + console.log("\nThen hit the 'any' key to continue..."); + } else { + cb(new Error("[acme-v2] unrecognized challenge type: " + cb.type)); + return; + } + + function onAny() { + console.log("'any' key was hit"); + process.stdin.pause(); + process.stdin.removeListener('data', onAny); + process.stdin.setRawMode(false); + cb(); + } + + process.stdin.setRawMode(true); + process.stdin.resume(); + process.stdin.on('data', onAny); + } + , removeChallenge: function (hostname, key, cb) { + console.log('[DEBUG] remove challenge', hostname, key); + setTimeout(cb, 1 * 1000); + } + , challengeType: chType + , email: email + , accountKeypair: accountKeypair + , domainKeypair: domainKeypair + , domains: web + }; + + acme2.registerNewAccount(options, function (err, account) { + if (err) { console.log('err 2'); throw err; } + if (options.debug) console.debug('account:'); + if (options.debug) console.log(account); + + acme2.getCertificate(options, function (err, fullchainPem) { + if (err) { console.log('err 3'); throw err; } + console.log('[acme-v2] A fullchain.pem:'); + console.log(fullchainPem); + }); + }); + }); +}; diff --git a/express-server/node_modules/acme-v2/tests/fullchain-formats.js b/express-server/node_modules/acme-v2/tests/fullchain-formats.js new file mode 100644 index 00000000..cb4f67cf --- /dev/null +++ b/express-server/node_modules/acme-v2/tests/fullchain-formats.js @@ -0,0 +1,77 @@ +'use strict'; + +/* +-----BEGIN CERTIFICATE-----LF +xxxLF +yyyLF +-----END CERTIFICATE-----LF +LF +-----BEGIN CERTIFICATE-----LF +xxxLF +yyyLF +-----END CERTIFICATE-----LF + +Rules + * Only Unix LF (\n) Line endings + * Each PEM's lines are separated with \n + * Each PEM ends with \n + * Each PEM is separated with a \n (just like commas separating an array) +*/ + +// https://github.com/certbot/certbot/issues/5721#issuecomment-402362709 +var expected = "----\nxxxx\nyyyy\n----\n\n----\nxxxx\nyyyy\n----\n"; +var tests = [ + "----\r\nxxxx\r\nyyyy\r\n----\r\n\r\n----\r\nxxxx\r\nyyyy\r\n----\r\n" +, "----\r\nxxxx\r\nyyyy\r\n----\r\n----\r\nxxxx\r\nyyyy\r\n----\r\n" +, "----\nxxxx\nyyyy\n----\n\n----\r\nxxxx\r\nyyyy\r\n----" +, "----\nxxxx\nyyyy\n----\n----\r\nxxxx\r\nyyyy\r\n----" +, "----\nxxxx\nyyyy\n----\n----\nxxxx\nyyyy\n----" +, "----\nxxxx\nyyyy\n----\n----\nxxxx\nyyyy\n----\n" +, "----\nxxxx\nyyyy\n----\n\n----\nxxxx\nyyyy\n----\n" +, "----\nxxxx\nyyyy\n----\r\n----\nxxxx\ryyyy\n----\n" +]; + +function formatPemChain(str) { + return str.trim().replace(/[\r\n]+/g, '\n').replace(/\-\n\-/g, '-\n\n-') + '\n'; +} +function splitPemChain(str) { + return str.trim().split(/[\r\n]{2,}/g).map(function (str) { + return str + '\n'; + }); +} + +tests.forEach(function (str) { + var actual = formatPemChain(str); + if (expected !== actual) { + console.error('input: ', JSON.stringify(str)); + console.error('expected:', JSON.stringify(expected)); + console.error('actual: ', JSON.stringify(actual)); + throw new Error("did not pass"); + } +}); + +if ( + "----\nxxxx\nyyyy\n----\n" + !== + formatPemChain("\n\n----\r\nxxxx\r\nyyyy\r\n----\n\n") +) { + throw new Error("Not proper for single cert in chain"); +} + +if ( + "--B--\nxxxx\nyyyy\n--E--\n\n--B--\nxxxx\nyyyy\n--E--\n\n--B--\nxxxx\nyyyy\n--E--\n" + !== + formatPemChain("\n\n\n--B--\nxxxx\nyyyy\n--E--\n\n\n\n--B--\nxxxx\nyyyy\n--E--\n\n\n--B--\nxxxx\nyyyy\n--E--\n\n\n") +) { + throw new Error("Not proper for three certs in chain"); +} + +splitPemChain( + "--B--\nxxxx\nyyyy\n--E--\n\n--B--\nxxxx\nyyyy\n--E--\n\n--B--\nxxxx\nyyyy\n--E--\n" +).forEach(function (str) { + if ("--B--\nxxxx\nyyyy\n--E--\n" !== str) { + throw new Error("bad thingy"); + } +}); + +console.info('PASS'); diff --git a/express-server/node_modules/acme-v2/tests/promise.js b/express-server/node_modules/acme-v2/tests/promise.js new file mode 100644 index 00000000..7c1c17f1 --- /dev/null +++ b/express-server/node_modules/acme-v2/tests/promise.js @@ -0,0 +1,85 @@ +'use strict'; + +/* global Promise */ +module.exports.run = function run(directoryUrl, RSA, web, chType, email, accountKeypair, domainKeypair) { + var acme2 = require('../').ACME.create({ RSA: RSA }); + // [ 'test.ppl.family' ] 'coolaj86@gmail.com''http-01' + acme2.init(directoryUrl).then(function () { + var options = { + agreeToTerms: function (tosUrl) { + return Promise.resolve(tosUrl); + } + , setChallenge: function (opts) { + return new Promise(function (resolve, reject) { + var pathname; + + console.log(""); + console.log('identifier:'); + console.log(opts.identifier); + console.log('hostname:'); + console.log(opts.hostname); + console.log('type:'); + console.log(opts.type); + console.log('token:'); + console.log(opts.token); + console.log('thumbprint:'); + console.log(opts.thumbprint); + console.log('keyAuthorization:'); + console.log(opts.keyAuthorization); + console.log('dnsAuthorization:'); + console.log(opts.dnsAuthorization); + console.log(""); + + if ('http-01' === opts.type) { + pathname = opts.hostname + acme2.challengePrefixes['http-01'] + "/" + opts.token; + console.log("Put the string '" + opts.keyAuthorization + "' into a file at '" + pathname + "'"); + console.log("echo '" + opts.keyAuthorization + "' > '" + pathname + "'"); + } else if ('dns-01' === opts.type) { + pathname = acme2.challengePrefixes['dns-01'] + "." + opts.hostname.replace(/^\*\./, ''); + console.log("Put the string '" + opts.dnsAuthorization + "' into the TXT record '" + pathname + "'"); + console.log("dig TXT " + pathname + " '" + opts.dnsAuthorization + "'"); + } else { + reject(new Error("[acme-v2] unrecognized challenge type")); + return; + } + console.log("\nThen hit the 'any' key to continue..."); + + function onAny() { + console.log("'any' key was hit"); + process.stdin.pause(); + process.stdin.removeListener('data', onAny); + process.stdin.setRawMode(false); + resolve(); + return; + } + + process.stdin.setRawMode(true); + process.stdin.resume(); + process.stdin.on('data', onAny); + }); + } + , removeChallenge: function (opts) { + console.log('[acme-v2] remove challenge', opts.hostname, opts.keyAuthorization); + return new Promise(function (resolve) { + // hostname, key + setTimeout(resolve, 1 * 1000); + }); + } + , challengeType: chType + , email: email + , accountKeypair: accountKeypair + , domainKeypair: domainKeypair + , domains: web + }; + + acme2.accounts.create(options).then(function (account) { + console.log('[acme-v2] account:'); + console.log(account); + + acme2.certificates.create(options).then(function (fullchainPem) { + console.log('[acme-v2] fullchain.pem:'); + console.log(fullchainPem); + }); + }); + }); +}; diff --git a/express-server/node_modules/acme/LICENSE b/express-server/node_modules/acme/LICENSE new file mode 100644 index 00000000..693448ab --- /dev/null +++ b/express-server/node_modules/acme/LICENSE @@ -0,0 +1,41 @@ +Copyright 2018 AJ ONeal + +This is open source software; you can redistribute it and/or modify it under the +terms of either: + + a) the "MIT License" + b) the "Apache-2.0 License" + +MIT License + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + +Apache-2.0 License Summary + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/express-server/node_modules/acme/README.md b/express-server/node_modules/acme/README.md new file mode 100644 index 00000000..30d73ba8 --- /dev/null +++ b/express-server/node_modules/acme/README.md @@ -0,0 +1,233 @@ +acme.js +========== + +Free SSL for everybody. The bare essentials of the Let's Encrypt v2 (ACME) API. +Built for [Greenlock](https://git.coolaj86.com/coolaj86/greenlock-express.js), +[by request](https://git.coolaj86.com/coolaj86/greenlock.js/issues/5#issuecomment-8). + +| Sponsored by [ppl](https://ppl.family) | +!["Monthly Downloads"](https://img.shields.io/npm/dm/acme-v2.svg "Monthly Download Count can't be shown") +!["Weekly Downloads"](https://img.shields.io/npm/dw/acme-v2.svg "Weekly Download Count can't be shown") + +Looking for Quick 'n' Easy™? +======= + +This is intented for building ACME API clients in node.js. It is **not** a high-level, fully-integrated solution. + +You may be more interested in one of these: + +* Instant SSL Certificates in your Browser +* [Greenlock for Web Browsers](https://git.coolaj86.com/coolaj86/greenlock.html) (Browser JavaScript) +* [Greenlock for Web Servers](https://git.coolaj86.com/coolaj86/greenlock-cli.js) (Command line, like certbot) +* [Greenlock for Express.js](https://git.coolaj86.com/coolaj86/greenlock-express.js) (Automated HTTPS for Express.js apps) +* [Greenlock for node.js](https://git.coolaj86.com/coolaj86/greenlock.js) (Automated HTTPS for Proxies, Load-Balances, Servers, CLIs) +* [goldilocks.js](https://git.coolaj86.com/coolaj86/goldilocks.js) (A Full-Blown WebServer) + +Demonstration +============= + +As this is intended to *build* ACME clients, there is not a simple 2-line example. + +I'd recommend first trying out one of the [Greenlock for Web Servers](https://git.coolaj86.com/coolaj86/greenlock-cli.js) +examples, which are guaranteed to work and have great error checking to help you debug. + +Then I'd recommend running the example CLI client with a test domain and then investigating the files used for that example: + +```bash +git clone https://git.coolaj86.com/coolaj86/acme.js.git +pushd acme.js/ +node examples/cli.js +``` + +The example cli has the following prompts: + +``` +What web address(es) would you like to get certificates for? (ex: example.com,*.example.com) +What challenge will you be testing today? http-01 or dns-01? [http-01] +What email should we use? (optional) +What directoryUrl should we use? [https://acme-staging-v02.api.letsencrypt.org/directory] + +Put the string 'mBfh0SqaAV3MOK3B6cAhCbIReAyDuwuxlO1Sl70x6bM.VNAzCR4THe4czVzo9piNn73B1ZXRLaB2CESwJfKkvRM' into a file at 'example.com/.well-known/acme-challenge/mBfh0SqaAV3MOK3B6cAhCbIReAyDuwuxlO1Sl70x6bM' + +echo 'mBfh0SqaAV3MOK3B6cAhCbIReAyDuwuxlO1Sl70x6bM.VNAzCR4THe4czVzo9piNn73B1ZXRLaB2CESwJfKkvRM' > 'example.com/.well-known/acme-challenge/mBfh0SqaAV3MOK3B6cAhCbIReAyDuwuxlO1Sl70x6bM' + +Then hit the 'any' key to continue... +``` + +When you've completed the challenge you can hit a key to continue the process. + +If you place the certificate you receive back in `tests/fullchain.pem` +then you can test it with `examples/https-server.js`. + +``` +examples/cli.js +examples/genkeypair.js +examples/https-server.js +examples/http-server.js +``` + +Let's Encrypt v2 / ACME draft 11 Support +======== + +This library (acme.js) supports ACME [*draft 11*](https://tools.ietf.org/html/draft-ietf-acme-acme-11), +otherwise known as Let's Encrypt v2 (or v02). + + * ACME draft 11 + * Let's Encrypt v2 + * Let's Encrypt v02 + +``` +# Production URL +https://acme-v02.api.letsencrypt.org/directory +``` + +``` +# Staging URL +https://acme-staging-v02.api.letsencrypt.org/directory +``` + +Install +======= + +Install via npm + +```bash +npm install --save acme +``` + +Install via git + +```bash +npm install https://git.coolaj86.com/coolaj86/acme.js.git +``` + +API +=== + +This API is an evolution of le-acme-core, +but tries to provide a better mapping to the new draft 11 APIs. + +Status: Almost stable, but **not semver locked**. + +Patch versions will not introduce breaking changes, +but may introduce lower-level APIs. +Minor versions may change return values to include more information. + +### Overview + +``` +var ACME = require('acme').ACME; + +ACME.create(opts) + +acme.init(acmeDirectoryUrl) +acme.accounts.create(opts) +acme.certificates.create(opts) +``` + +### Detailed Explanation + +``` +var ACME = require('acme').ACME; + +// Create Instance (Dependency Injection) +var acme = ACME.create({ + RSA: require('rsa-compat').RSA + + // other overrides +, request: require('request') +, promisify: require('util').promisify + + // used for constructing user-agent +, os: require('os') +, process: require('process') + + // used for overriding the default user-agent +, userAgent: 'My custom UA String' +, getUserAgentString: function (deps) { return 'My custom UA String'; } + + // don't try to validate challenges locally +, skipChallengeTest: false +}); + + +// Discover Directory URLs +acme.init(acmeDirectoryUrl) // returns Promise + + +// Accounts +acme.accounts.create(options) // returns Promise registration data + + { email: '' // valid email (server checks MX records) + , accountKeypair: { // privateKeyPem or privateKeyJwt + privateKeyPem: '' + } + , agreeToTerms: fn (tosUrl) {} // returns Promise with tosUrl + } + + +// Registration +acme.certificates.create(options) // returns Promise + + { newAuthzUrl: '' // specify acmeUrls.newAuthz + , newCertUrl: '' // specify acmeUrls.newCert + + , domainKeypair: { + privateKeyPem: '' + } + , accountKeypair: { + privateKeyPem: '' + } + , domains: [ 'example.com' ] + + , setChallenge: fn (hostname, key, val) // return Promise + , removeChallenge: fn (hostname, key) // return Promise + } +``` + +Helpers & Stuff + +```javascript +// Constants +ACME.challengePrefixes['http-01'] // '/.well-known/acme-challenge' +ACME.challengePrefixes['dns-01'] // '_acme-challenge' +``` + +Changelog +--------- + +* v1.0.9 - update docs +* v1.0.8 - rename to acme.js, remove backwards compat +* v1.0.7 - improved error handling again, after user testing +* v1.0.6 - improved error handling +* v1.0.5 - cleanup logging +* v1.0.4 - v6- compat use `promisify` from node's util or bluebird +* v1.0.3 - documentation cleanup +* v1.0.2 + * use `options.contact` to provide raw contact array + * made `options.email` optional + * file cleanup +* v1.0.1 + * Compat API is ready for use + * Eliminate debug logging +* Apr 10, 2018 - tested backwards-compatibility using greenlock.js +* Apr 5, 2018 - export http and dns challenge tests +* Apr 5, 2018 - test http and dns challenges (success and failure) +* Apr 5, 2018 - test subdomains and its wildcard +* Apr 5, 2018 - test two subdomains +* Apr 5, 2018 - test wildcard +* Apr 5, 2018 - completely match api for acme v1 (le-acme-core.js) +* Mar 21, 2018 - *mostly* matches le-acme-core.js API +* Mar 21, 2018 - can now accept values (not hard coded) +* Mar 20, 2018 - SUCCESS - got a test certificate (hard-coded) +* Mar 20, 2018 - download certificate +* Mar 20, 2018 - poll for status +* Mar 20, 2018 - finalize order (submit csr) +* Mar 20, 2018 - generate domain keypair +* Mar 20, 2018 - respond to challenges +* Mar 16, 2018 - get challenges +* Mar 16, 2018 - new order +* Mar 15, 2018 - create account +* Mar 15, 2018 - generate account keypair +* Mar 15, 2018 - get nonce +* Mar 15, 2018 - get directory diff --git a/express-server/node_modules/acme/examples/cli.js b/express-server/node_modules/acme/examples/cli.js new file mode 100644 index 00000000..0dd7a15e --- /dev/null +++ b/express-server/node_modules/acme/examples/cli.js @@ -0,0 +1,64 @@ +'use strict'; + +var readline = require('readline'); +var inquisitor = {}; +var rl = readline.createInterface({ + input: process.stdin, + output: process.stdout +}); + +require('./genkeypair.js'); + +inquisitor.getWeb = function getWeb() { + rl.question('What web address(es) would you like to get certificates for? (ex: example.com,*.example.com) ', function (web) { + web = (web||'').trim().split(/,/g); + if (!web[0]) { inquisitor.getWeb(); return; } + + if (web.some(function (w) { return '*' === w[0]; })) { + console.log('Wildcard domains must use dns-01'); + inquisitor.getEmail(web, 'dns-01'); + } else { + inquisitor.getChallengeType(web); + } + }); +}; + +inquisitor.getChallengeType = function getChallengeType(web) { + rl.question('What challenge will you be testing today? http-01 or dns-01? [http-01] ', function (chType) { + chType = (chType||'').trim(); + if (!chType) { chType = 'http-01'; } + + inquisitor.getEmail(web, chType); + }); +}; + +inquisitor.getEmail = function getEmail(web, chType) { + rl.question('What email should we use? (optional) ', function (email) { + email = (email||'').trim(); + if (!email) { email = null; } + + inquisitor.getDirectoryUrl(web, chType, email); + }); +}; + +inquisitor.getDirectoryUrl = function getDirectoryUrl(web, chType, email) { + var defaultDirectoryUrl = 'https://acme-staging-v02.api.letsencrypt.org/directory'; + rl.question('What directoryUrl should we use? [' + defaultDirectoryUrl + '] ', function (directoryUrl) { + directoryUrl = (directoryUrl||'').trim(); + if (!directoryUrl) { directoryUrl = 'https://acme-staging-v02.api.letsencrypt.org/directory'; } + + inquisitor.run(directoryUrl, web, chType, email); + }); +}; + +inquisitor.run = function run(directoryUrl, web, chType, email) { + rl.close(); + + var RSA = require('rsa-compat').RSA; + var accountKeypair = RSA.import({ privateKeyPem: require('fs').readFileSync(__dirname + '/../tests/account.privkey.pem') }); + var domainKeypair = RSA.import({ privateKeyPem: require('fs').readFileSync(__dirname + '/../tests/privkey.pem') }); + + require('../tests/promise.js').run(directoryUrl, RSA, web, chType, email, accountKeypair, domainKeypair); +}; + +inquisitor.getWeb(); diff --git a/express-server/node_modules/acme/examples/genkeypair.js b/express-server/node_modules/acme/examples/genkeypair.js new file mode 100644 index 00000000..2c7e3c62 --- /dev/null +++ b/express-server/node_modules/acme/examples/genkeypair.js @@ -0,0 +1,22 @@ +var RSA = require('rsa-compat').RSA; +var fs = require('fs'); + +if (!fs.existsSync(__dirname + '/../tests/account.privkey.pem')) { + RSA.generateKeypair(2048, 65537, {}, function (err, keypair) { + console.log(keypair); + var privkeyPem = RSA.exportPrivatePem(keypair) + console.log(privkeyPem); + + fs.writeFileSync(__dirname + '/../tests/account.privkey.pem', privkeyPem); + }); +} + +if (!fs.existsSync(__dirname + '/../tests/privkey.pem')) { + RSA.generateKeypair(2048, 65537, {}, function (err, keypair) { + console.log(keypair); + var privkeyPem = RSA.exportPrivatePem(keypair) + console.log(privkeyPem); + + fs.writeFileSync(__dirname + '/../tests/privkey.pem', privkeyPem); + }); +} diff --git a/express-server/node_modules/acme/examples/http-server.js b/express-server/node_modules/acme/examples/http-server.js new file mode 100644 index 00000000..4195455d --- /dev/null +++ b/express-server/node_modules/acme/examples/http-server.js @@ -0,0 +1,7 @@ +'use strict'; + +var http = require('http'); +var express = require('express'); +var server = http.createServer(express.static('../tests')).listen(80, function () { + console.log('Listening on', this.address()); +}); diff --git a/express-server/node_modules/acme/examples/https-server.js b/express-server/node_modules/acme/examples/https-server.js new file mode 100644 index 00000000..5dd2c2c9 --- /dev/null +++ b/express-server/node_modules/acme/examples/https-server.js @@ -0,0 +1,11 @@ +'use strict'; + +var https = require('https'); +var server = https.createServer({ + key: require('fs').readFileSync('../tests/privkey.pem') +, cert: require('fs').readFileSync('../tests/fullchain.pem') +}, function (req, res) { + res.end("Hello, World!"); +}).listen(443, function () { + console.log('Listening on', this.address()); +}); diff --git a/express-server/node_modules/acme/node.js b/express-server/node_modules/acme/node.js new file mode 100644 index 00000000..b346c956 --- /dev/null +++ b/express-server/node_modules/acme/node.js @@ -0,0 +1,3 @@ +// For the time being I'm still pulling in my acme-v2 module until I transition over +// I export as ".ACME" rather than bare so that this can be compatible with the browser version too +module.exports.ACME = require('acme-v2').ACME; diff --git a/express-server/node_modules/acme/package.json b/express-server/node_modules/acme/package.json new file mode 100644 index 00000000..849bd1f4 --- /dev/null +++ b/express-server/node_modules/acme/package.json @@ -0,0 +1,109 @@ +{ + "_args": [ + [ + "acme@^1.0.6", + "/nodeapps/https-test/greenlock-express.js/node_modules/greenlock" + ] + ], + "_from": "acme@>=1.0.6 <2.0.0", + "_id": "acme@1.1.1", + "_inCache": true, + "_installable": true, + "_location": "/acme", + "_nodeVersion": "10.2.1", + "_npmOperationalInternal": { + "host": "s3://npm-registry-packages", + "tmp": "tmp/acme_1.1.1_1530693806508_0.5374627943153449" + }, + "_npmUser": { + "email": "coolaj86@gmail.com", + "name": "coolaj86" + }, + "_npmVersion": "5.6.0", + "_phantomChildren": {}, + "_requested": { + "name": "acme", + "raw": "acme@^1.0.6", + "rawSpec": "^1.0.6", + "scope": null, + "spec": ">=1.0.6 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/greenlock" + ], + "_resolved": "https://registry.npmjs.org/acme/-/acme-1.1.1.tgz", + "_shasum": "8831797657303336eb3d3d06f42d6152081f42bf", + "_shrinkwrap": null, + "_spec": "acme@^1.0.6", + "_where": "/nodeapps/https-test/greenlock-express.js/node_modules/greenlock", + "author": { + "email": "coolaj86@gmail.com", + "name": "AJ ONeal", + "url": "https://coolaj86.com/" + }, + "dependencies": { + "acme-v2": "^1.1.0" + }, + "description": "The bare essentials of the ACME (Let's Encrypt v2) API. This is a low-level library for building high-level clients.", + "devDependencies": {}, + "directories": {}, + "dist": { + "fileCount": 9, + "integrity": "sha512-CZFTpD2hGSE8dd63vHtvdhabondEhgmpL0wH0weV0pk+I1WH9RVcJbdR6MgoalsUtJW/SaC+OxUDrcjINur1ow==", + "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbPIiuCRA9TVsSAnZWagAAFEcP/34ebMMxTtSVjlKkNxZQ\n80AmVT4ESDenhRX3buCUgWuUAiK0q9K5eTel+Mj7ijElXLFzmA56VdwbaZKr\ng+5WRm3DfXA2/rGOHztLlbBXwO3Gcn6X28SUIg8R6xLrC9Z/KVd5smygOiIY\nqgmjhaDZcMxE9Wehkl6v0fYjsP0KQF6OT19f8YMHOw9m9dIJBLaJFxPVONuT\nu9XLzMnCWmsMhc2T/a+dZAHTZmZYMS0PqnJJ7S8x14+kvEiCaVME1XqSgwHv\nIagQUVICle3CLvyJaS5XnTjbxC6swd8S79IG2lrko6r8bnieonvFdUKg8AHH\n7ejyPyLw6jcruUWn6sf5U/lv0pzMyD3aldDY5udYfkLVUDrJW+xratvGCWgZ\nxwIsk9nQrnft6zhiHSuF/J7c+MRcG0i1DkXmm8gQxph4lI4KlQcfhHz1b8QI\nvGbAhk4qAphaOch0HSmFwPRv3cfEPZ03/IXQanGov2D0OLm2Zf9+BnE3Jq27\nkmrFSKbsm2LZEGK+ei7jPiXErVGP1HQx5oS59+ZAhT1QhaI/J1bha33iiyGg\nsWi5QGCxrIXY8wLgH20e4boOqUMAAkL1m3SPChCVHWl6Z2Xv9is/02oYrSmN\n5d/yb8yO34SykrrnsKx2Sj3z3xXOebdNqCob1pwL1mZC2+ccMEUsTj8GiFSQ\nQNJX\r\n=v/wZ\r\n-----END PGP SIGNATURE-----\r\n", + "shasum": "8831797657303336eb3d3d06f42d6152081f42bf", + "tarball": "https://registry.npmjs.org/acme/-/acme-1.1.1.tgz", + "unpackedSize": 17077 + }, + "gitHead": "71ae7393cbf816aa9eef85bfb9722bcee82feefb", + "homepage": "https://git.coolaj86.com/coolaj86/acme.js", + "keywords": [ + "11", + "Let's Encrypt", + "acme", + "acme-draft-11", + "acme-draft11", + "acme-v02", + "acme-v2", + "acme11", + "acme2", + "acmev02", + "acmev2", + "draft", + "greenlock", + "greenlock2", + "https", + "letsencrypt", + "letsencrypt-v02", + "letsencrypt-v2", + "letsencrypt2", + "letsencryptv02", + "letsencryptv2", + "ssl", + "tls" + ], + "license": "(MIT OR Apache-2.0)", + "main": "node.js", + "maintainers": [ + { + "name": "coolaj86", + "email": "coolaj86@gmail.com" + }, + { + "name": "thejshaver", + "email": "john@jshaver.net" + } + ], + "name": "acme", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "ssh://gitea@git.coolaj86.com:22042/coolaj86/acme.js.git" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "version": "1.1.1" +} diff --git a/express-server/node_modules/acme/tests/promise.js b/express-server/node_modules/acme/tests/promise.js new file mode 100644 index 00000000..ee2a0287 --- /dev/null +++ b/express-server/node_modules/acme/tests/promise.js @@ -0,0 +1,85 @@ +'use strict'; + +/* global Promise */ +module.exports.run = function run(directoryUrl, RSA, web, chType, email, accountKeypair, domainKeypair) { + var acme2 = require('../').ACME.create({ RSA: RSA }); + // [ 'test.ppl.family' ] 'coolaj86@gmail.com''http-01' + acme2.init(directoryUrl).then(function () { + var options = { + agreeToTerms: function (tosUrl) { + return Promise.resolve(tosUrl); + } + , setChallenge: function (opts) { + return new Promise(function (resolve, reject) { + var pathname; + + console.log(""); + console.log('identifier:'); + console.log(opts.identifier); + console.log('hostname:'); + console.log(opts.hostname); + console.log('type:'); + console.log(opts.type); + console.log('token:'); + console.log(opts.token); + console.log('thumbprint:'); + console.log(opts.thumbprint); + console.log('keyAuthorization:'); + console.log(opts.keyAuthorization); + console.log('dnsAuthorization:'); + console.log(opts.dnsAuthorization); + console.log(""); + + if ('http-01' === opts.type) { + pathname = opts.hostname + acme2.challengePrefixes['http-01'] + "/" + opts.token; + console.log("Put the string '" + opts.keyAuthorization + "' into a file at '" + pathname + "'"); + console.log("echo '" + opts.keyAuthorization + "' > '" + pathname + "'"); + } else if ('dns-01' === opts.type) { + pathname = acme2.challengePrefixes['dns-01'] + "." + opts.hostname.replace(/^\*\./, '');; + console.log("Put the string '" + opts.dnsAuthorization + "' into the TXT record '" + pathname + "'"); + console.log("ddig TXT " + pathname + " '" + opts.dnsAuthorization + "'"); + } else { + reject(new Error("[acme-v2] unrecognized challenge type")); + return; + } + console.log("\nThen hit the 'any' key to continue..."); + + function onAny() { + console.log("'any' key was hit"); + process.stdin.pause(); + process.stdin.removeListener('data', onAny); + process.stdin.setRawMode(false); + resolve(); + return; + } + + process.stdin.setRawMode(true); + process.stdin.resume(); + process.stdin.on('data', onAny); + }); + } + , removeChallenge: function (opts) { + console.log('[acme-v2] remove challenge', opts.hostname, opts.keyAuthorization); + return new Promise(function (resolve) { + // hostname, key + setTimeout(resolve, 1 * 1000); + }); + } + , challengeType: chType + , email: email + , accountKeypair: accountKeypair + , domainKeypair: domainKeypair + , domains: web + }; + + acme2.accounts.create(options).then(function (account) { + console.log('[acme-v2] account:'); + console.log(account); + + acme2.certificates.create(options).then(function (fullchainPem) { + console.log('[acme-v2] fullchain.pem:'); + console.log(fullchainPem); + }); + }); + }); +}; diff --git a/express-server/node_modules/asn1js/.gitattributes b/express-server/node_modules/asn1js/.gitattributes new file mode 100644 index 00000000..1ff0c423 --- /dev/null +++ b/express-server/node_modules/asn1js/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/express-server/node_modules/asn1js/.npmignore b/express-server/node_modules/asn1js/.npmignore new file mode 100644 index 00000000..1bc915c5 --- /dev/null +++ b/express-server/node_modules/asn1js/.npmignore @@ -0,0 +1,156 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +build/ +[Bb]in/ +[Oo]bj/ + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +!packages/*/build/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +#packages/ + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + + +#LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml + +# ========================= +# Windows detritus +# ========================= + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac desktop service store files +.DS_Store diff --git a/express-server/node_modules/asn1js/CNAME b/express-server/node_modules/asn1js/CNAME new file mode 100644 index 00000000..769f43cf --- /dev/null +++ b/express-server/node_modules/asn1js/CNAME @@ -0,0 +1 @@ +asn1js.org diff --git a/express-server/node_modules/asn1js/LICENSE b/express-server/node_modules/asn1js/LICENSE new file mode 100644 index 00000000..4f71696a --- /dev/null +++ b/express-server/node_modules/asn1js/LICENSE @@ -0,0 +1,30 @@ +Copyright (c) 2014, GMO GlobalSign +Copyright (c) 2015, Peculiar Ventures +All rights reserved. + +Author 2014-2015, Yury Strozhevsky + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* 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. + +* Neither the name of the copyright holder 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. diff --git a/express-server/node_modules/asn1js/README.md b/express-server/node_modules/asn1js/README.md new file mode 100644 index 00000000..75b50978 --- /dev/null +++ b/express-server/node_modules/asn1js/README.md @@ -0,0 +1,212 @@ +## ASN1js + +[![license](https://img.shields.io/badge/license-BSD-green.svg?style=flat)](https://raw.githubusercontent.com/GlobalSign/ASN1.js/master/LICENSE) + +Abstract Syntax Notation One (ASN.1) is a standard and notation that describes rules and structures for representing, encoding, transmitting, and decoding data in telecommunications and computer networking. [ASN1js][] is a pure JavaScript library implementing this standard. ASN.1 is the basis of all X.509 related data structures and numerous other protocols used on the web. + +## Introduction + +[ASN1js][] is the first library for [BER][] encoding/decoding in Javascript designed for browser use. [BER][] is the basic encoding rules for [ASN.1][] that all others are based on, [DER][] is the encoding rules used by PKI applications - it is a subset of [BER][]. The [ASN1js][] library was tested against [freely available ASN.1:2008 test suite], with some limitations related to JavaScript language. + +## Features of the library + +* [ASN1js][] is a "base layer" for full-featured JS library [PKIjs][], which is using Web Cryptography API and has all classes, neccessary to work with PKI-related data; +* Fully object-oriented library. Inhiritence is using everywhere inside the lib; +* Working with HTML5 data objects (ArrayBuffer, Uint8Array etc.); +* Working with all ASN.1:2008 types; +* Working with [BER][] encoded data; +* All types inside the library constantly stores information about all ASN.1 sub blocks (tag block, length block or value block); +* User may have access to any byte inside any ASN.1 sub-block; +* Any sub-block may have unlimited length, as it described in ASN.1 standard (even "tag block"); +* Ability to work with ASN.1 string date types (intcluding all "international" strings like UniversalString, BMPString, UTF8String) by passing native JavaScript strings into constuctors. And vice versa - all initially parsed data of ASN.1 string types right after decoding automatically converts into native JavaScript strings; +* Same with ASN.1 date-time types: for major types like UTCTime and GeneralizedTime there are automatic convertion between "JS date type - ASN.1 date-time type" + vice versa; +* Same with ASN.1 OBJECT-IDENTIFIER (OID) data-type: you can initialize OID by JavaScript string and can get string representation via calling "oid.value_block.toString()"; +* Working with "easy-to-understand" ASN.1 schemas (pre-defined or built by user); +* Has special types to work with ASN.1 schemas: + * ANY + * CHOICE + * REPEATED +* User can name any block inside ASN.1 schema and easily get information by name; +* Ability to parse internal data inside a primitively encoded data types and automatically validate it against special schema; +* All types inside library are dynamic; +* All types can be initialized in static or dynamic ways. + +## Examples + +```javascript + // #region How to create new ASN. structures + var sequence = new org.pkijs.asn1.SEQUENCE(); + sequence.value_block.value.push(new org.pkijs.asn1.INTEGER({ value: 1 })); + + var sequence_buffer = sequence.toBER(false); // Encode current sequence to BER (in ArrayBuffer) + var current_size = sequence_buffer.byteLength; + + var integer_data = new ArrayBuffer(8); + var integer_view = new Uint8Array(integer_data); + integer_view[0] = 0x01; + integer_view[1] = 0x01; + integer_view[2] = 0x01; + integer_view[3] = 0x01; + integer_view[4] = 0x01; + integer_view[5] = 0x01; + integer_view[6] = 0x01; + integer_view[7] = 0x01; + + sequence.value_block.value.push(new org.pkijs.asn1.INTEGER({ + is_hex_only: true, + value_hex: integer_data + })); // Put too long for decoding INTEGER value + + sequence_buffer = sequence.toBER(false); + current_size = sequence_buffer.byteLength; + // #endregion +``` + +```javascript + // #region How to create new ASN.1 structures by calling constuctors with parameters + var sequence2 = new org.pkijs.asn1.SEQUENCE({ + value: [ + new org.pkijs.asn1.INTEGER({ value: 1 }), + new org.pkijs.asn1.INTEGER({ + is_hex_only: true, + value_hex: integer_data + }), + ] + }); + // #endregion +``` + +```javascript + // #region How to validate ASN.1 against pre-defined schema + var asn1_schema = new org.pkijs.asn1.SEQUENCE({ + name: "block1", + value: [ + new org.pkijs.asn1.NULL({ + name: "block2" + }), + new org.pkijs.asn1.INTEGER({ + name: "block3", + optional: true // This block is absent inside data, but it's "optional". Hence verification against the schema will be passed. + }) + ] + }); + // #endregion + + var variant1 = org.pkijs.verifySchema(encoded_sequence, asn1_schema); // Verify schema together with decoding of raw data + var variant1_verified = variant1.verified; + var variant1_result = variant1.result; // Verified decoded data with all block names inside +``` + +```javascript + // #region How to use "internal schemas" for primitevely encoded data types + var primitive_octetstring = new org.pkijs.asn1.OCTETSTRING({ value_hex: encoded_sequence }); // Create a primitively encoded OCTETSTRING where internal data is an encoded SEQUENCE + + var asn1_schema_internal = new org.pkijs.asn1.OCTETSTRING({ + name: "outer_block", + primitive_schema: new org.pkijs.asn1.SEQUENCE({ + name: "block1", + value: [ + new org.pkijs.asn1.NULL({ + name: "block2" + }) + ] + }) + }); + + var variant6 = org.pkijs.compareSchema(primitive_octetstring, primitive_octetstring, asn1_schema_internal); + var variant6_verified = variant4.verified; + var variant6_block1_tag_num = variant6.result.block1.id_block.tag_number; + var variant6_block2_tag_num = variant6.result.block2.id_block.tag_number; + // #endregion +``` + +More examples could be found in "examples" directory or inside [PKIjs][] library. + +## Related source code + +* [C++ ASN1:2008 BER coder/decoder](https://github.com/YuryStrozhevsky/C-plus-plus-ASN.1-2008-coder-decoder) - the "father" of [ASN1js][] project; +* [Freely available ASN.1:2008 test suite](https://github.com/YuryStrozhevsky/ASN1-2008-free-test-suite) - the suite which can help you to validate (and better understand) any ASN.1 coder/decoder; + +## Suitability +At this time this library should be considered suitable for research and experimentation, futher code and security review is needed before utilization in a production application. + +## How to use ASN1js and PKIjs with Node.js + +**!!! WARNING !!! ** +**Currently there is no "polyfill" of WebCrypto in Node.js. Thus you will not be able to use signature / verification features of PKIjs in Node.js programs.** + +In order to use [PKIjs][] you will also need [ASN1js][] plus [node.extend](https://www.npmjs.com/package/node.extend) package. +```javascript + var merge = require("node.extend"); + + var common = require("asn1js/org/pkijs/common"); + var _asn1js = require("asn1js"); + var _pkijs = require("pkijs"); + var _x509schema = require("pkijs/org/pkijs/x509_schema"); + + // #region Merging function/object declarations for ASN1js and PKIjs + var asn1js = merge(true, _asn1js, common); + + var x509schema = merge(true, _x509schema, asn1js); + + var pkijs_1 = merge(true, _pkijs, asn1js); + var pkijs = merge(true, pkijs_1, x509schema); + // #endregion +``` + +After that you will ba able to use ASN1js and PKIjs via common way: +```javascript + // #region Decode and parse X.509 cert + var asn1 = pkijs.org.pkijs.fromBER(certBuffer); + var cert; + try + { + cert = new pkijs.org.pkijs.simpl.CERT({ schema: asn1.result }); + } + catch(ex) + { + return; + } + // #endregion +``` + +## License + +Copyright (c) 2014, [GMO GlobalSign](http://www.globalsign.com/) +Copyright (c) 2015, [Peculiar Ventures](http://peculiarventures.com/) +All rights reserved. + +Author 2014-2015, [Yury Strozhevsky](http://www.strozhevsky.com/). + +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 copyright holder 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. + + +[ASN.1]: http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One +[ASN1js]: http://asn1js.org/ +[PKIjs]: http://pkijs.org/ +[BER]: http://en.wikipedia.org/wiki/X.690#BER_encoding +[DER]: http://en.wikipedia.org/wiki/X.690#DER_encoding +[freely available ASN.1:2008 test suite]: http://www.strozhevsky.com/free_docs/free_asn1_testsuite_descr.pdf diff --git a/express-server/node_modules/asn1js/examples/ASN.1 usage/asn1_usage.js b/express-server/node_modules/asn1js/examples/ASN.1 usage/asn1_usage.js new file mode 100644 index 00000000..2e3ac557 --- /dev/null +++ b/express-server/node_modules/asn1js/examples/ASN.1 usage/asn1_usage.js @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2014, GMO GlobalSign + * Copyright (c) 2015, Peculiar Ventures + * All rights reserved. + * + * Author 2014-2015, Yury Strozhevsky . + * + * 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 copyright holder 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. + * + */ +//************************************************************************************** +function test() +{ + // #region How to create new ASN. structures + var sequence = new org.pkijs.asn1.SEQUENCE(); + sequence.value_block.value.push(new org.pkijs.asn1.INTEGER({ value: 1 })); + + var sequence_buffer = sequence.toBER(false); // Encode current sequence to BER (in ArrayBuffer) + var current_size = sequence_buffer.byteLength; + + var integer_data = new ArrayBuffer(8); + var integer_view = new Uint8Array(integer_data); + integer_view[0] = 0x01; + integer_view[1] = 0x01; + integer_view[2] = 0x01; + integer_view[3] = 0x01; + integer_view[4] = 0x01; + integer_view[5] = 0x01; + integer_view[6] = 0x01; + integer_view[7] = 0x01; + + sequence.value_block.value.push(new org.pkijs.asn1.INTEGER({ + is_hex_only: true, + value_hex: integer_data + })); // Put too long for decoding INTEGER value + + sequence_buffer = sequence.toBER(false); + current_size = sequence_buffer.byteLength; + // #endregion + + // #region How to create new ASN.1 structures by calling constuctors with parameters + var sequence2 = new org.pkijs.asn1.SEQUENCE({ + value: [ + new org.pkijs.asn1.INTEGER({ value: 1 }), + new org.pkijs.asn1.INTEGER({ + is_hex_only: true, + value_hex: integer_data + }), + ] + }); + // #endregion + + // #region How to check that decoded value is too big + var big_integer_value; + + var big_integer = new org.pkijs.asn1.INTEGER({ + is_hex_only: true, + value_hex: integer_data + }); + + if(big_integer.value_block.is_hex_only === false) + big_integer_value = big_integer.value_block.value_dec; // Native integer value + else + big_integer_value = big_integer.value_block.value_hex; // ArrayBuffer + // #endregion + + // #region How to get ASN.1 structures from raw data (ASN.1 decoding) + var encoded_sequence = new ArrayBuffer(4); + var encoded_sequence_view = new Uint8Array(encoded_sequence); + encoded_sequence_view[0] = 0x30; + encoded_sequence_view[1] = 0x02; + encoded_sequence_view[2] = 0x05; + encoded_sequence_view[3] = 0x00; + + var decoded_asn1 = org.pkijs.fromBER(encoded_sequence); + if(decoded_asn1.offset === (-1)) + return; // Error during decoding + + var decoded_sequence = decoded_asn1.result; + + var internal_value = decoded_sequence.value_block.value[0]; + var internal_value_tag_number = internal_value.id_block.tag_number; // Value of "5" equal to ASN.1 NULL type + // #endregion + + // #region How to work with ASN.1 strings + var bmp_string_encoded = new ArrayBuffer(16); // This ArrayBuffer consinsts of encoded ASN.1 BMPString with "abc_" + three first chars from Russian alphabet + var bmp_string_view = new Uint8Array(bmp_string_encoded); + bmp_string_view[0] = 0x1E; + bmp_string_view[1] = 0x0E; + bmp_string_view[2] = 0x00; + bmp_string_view[3] = 0x61; + bmp_string_view[4] = 0x00; + bmp_string_view[5] = 0x62; + bmp_string_view[6] = 0x00; + bmp_string_view[7] = 0x63; + bmp_string_view[8] = 0x00; + bmp_string_view[9] = 0x5F; + bmp_string_view[10] = 0x04; + bmp_string_view[11] = 0x30; + bmp_string_view[12] = 0x04; + bmp_string_view[13] = 0x31; + bmp_string_view[14] = 0x04; + bmp_string_view[15] = 0x32; + + var bmp_string_decoded = org.pkijs.fromBER(bmp_string_encoded); + if(bmp_string_decoded.offset === (-1)) + return; // Error during decoding + + var javascript_string1 = bmp_string_decoded.result.value_block.value; + + var bmp_string = new org.pkijs.asn1.BMPSTRING({ value: "abc_абв" }); // Same with initialization by static JavaScript string + var javascript_string2 = bmp_string.value_block.value; + // #endregion + + // #region How to validate ASN.1 against pre-defined schema + var asn1_schema = new org.pkijs.asn1.SEQUENCE({ + name: "block1", + value: [ + new org.pkijs.asn1.NULL({ + name: "block2" + }), + new org.pkijs.asn1.INTEGER({ + name: "block3", + optional: true // This block is absent inside data, but it's "optional". Hence verification against the schema will be passed. + }) + ] + }); + + var variant1 = org.pkijs.verifySchema(encoded_sequence, asn1_schema); // Verify schema together with decoding of raw data + var variant1_verified = variant1.verified; + var variant1_result = variant1.result; // Verified decoded data with all block names inside + + var variant1_block1 = variant1_result.block1; + var variant1_block2 = variant1_result.block2; + + var variant2 = org.pkijs.compareSchema(decoded_sequence, decoded_sequence, asn1_schema); // Compare already decoded ASN.1 against pre-defined schema + var variant2_verified = variant2.verified; + var variant2_result = variant2.result; // Verified decoded data with all block names inside + + var variant2_block1 = variant2_result.block1; + var variant2_block2 = variant2_result.block2; + + var asn1_schema_any = new org.pkijs.asn1.SEQUENCE({ + name: "block1", + value: [ + new org.pkijs.asn1.ANY({ // Special type, for ASN.1 schemas only - will validate schema against any ASN.1 type + name: "block2" + }) + ] + }); + + decoded_sequence = org.pkijs.fromBER(encoded_sequence).result; // Re-setting "decoded_sequence" + + var variant3 = org.pkijs.compareSchema(decoded_sequence, decoded_sequence, asn1_schema_any); + var variant3_verified = variant3.verified; + + var asn1_schema_repeated = new org.pkijs.asn1.SEQUENCE({ + name: "block1", + value: [ + new org.pkijs.asn1.REPEATED({ // Special type, for ASN.1 schemas only - will check that inside decoded data there are sequence of values with one type only + name: "block2_array", + value: new org.pkijs.asn1.NULL() + }) + ] + }); + + decoded_sequence = org.pkijs.fromBER(encoded_sequence).result; // Re-setting "decoded_sequence" + + var variant4 = org.pkijs.compareSchema(decoded_sequence, decoded_sequence, asn1_schema_repeated); + var variant4_verified = variant4.verified; + + var variant4_array = variant4.block2_array; // Array of internal blocks + + var asn1_schema_choice = new org.pkijs.asn1.SEQUENCE({ + name: "block1", + value: [ + new org.pkijs.asn1.CHOICE({ // Special type, for ASN.1 schemas only - will check ASN.1 data has one of type + value: [ + new org.pkijs.asn1.NULL({ + name: "block2" + }), + new org.pkijs.asn1.INTEGER({ + name: "block2" + }), + ] + }) + ] + }); + + decoded_sequence = org.pkijs.fromBER(encoded_sequence).result; // Re-setting "decoded_sequence" + + var variant5 = org.pkijs.compareSchema(decoded_sequence, decoded_sequence, asn1_schema_choice); + var variant5_verified = variant4.verified; + // #endregion + + // #region How to use "internal schemas" for primitevely encoded data types + var primitive_octetstring = new org.pkijs.asn1.OCTETSTRING({ value_hex: encoded_sequence }); // Create a primitively encoded OCTETSTRING where internal data is an encoded SEQUENCE + + var asn1_schema_internal = new org.pkijs.asn1.OCTETSTRING({ + name: "outer_block", + primitive_schema: new org.pkijs.asn1.SEQUENCE({ + name: "block1", + value: [ + new org.pkijs.asn1.NULL({ + name: "block2" + }) + ] + }) + }); + + var variant6 = org.pkijs.compareSchema(primitive_octetstring, primitive_octetstring, asn1_schema_internal); + var variant6_verified = variant4.verified; + var variant6_block1_tag_num = variant6.result.block1.id_block.tag_number; + var variant6_block2_tag_num = variant6.result.block2.id_block.tag_number; + // #endregion +} +//************************************************************************************** diff --git a/express-server/node_modules/asn1js/org/pkijs/asn1.js b/express-server/node_modules/asn1js/org/pkijs/asn1.js new file mode 100644 index 00000000..4c038a44 --- /dev/null +++ b/express-server/node_modules/asn1js/org/pkijs/asn1.js @@ -0,0 +1,5466 @@ +/* + * Copyright (c) 2014, GMO GlobalSign + * Copyright (c) 2015, Peculiar Ventures + * All rights reserved. + * + * Author 2014-2015, Yury Strozhevsky . + * + * 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 copyright holder 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. + * + */ +( +function(in_window) +{ + //************************************************************************************** + // #region Declaration of global variables + //************************************************************************************** + // #region "org" namespace + if(typeof in_window.org === "undefined") + in_window.org = {}; + else + { + if(typeof in_window.org !== "object") + throw new Error("Name org already exists and it's not an object"); + } + // #endregion + + // #region "org.pkijs" namespace + if(typeof in_window.org.pkijs === "undefined") + in_window.org.pkijs = {}; + else + { + if(typeof in_window.org.pkijs !== "object") + throw new Error("Name org.pkijs already exists and it's not an object" + " but " + (typeof in_window.org.pkijs)); + } + // #endregion + + // #region "org.pkijs.asn1" namespace + if(typeof in_window.org.pkijs.asn1 === "undefined") + in_window.org.pkijs.asn1 = {}; + else + { + if(typeof in_window.org.pkijs.asn1 !== "object") + throw new Error("Name org.pkijs.asn1 already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.asn1)); + } + // #endregion + + // #region "local" namespace + var local = {}; + // #endregion + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Aux-functions + //************************************************************************************** + function util_frombase(input_buffer, input_base) + { + /// Convert number from 2^base to 2^10 + /// Array of bytes representing the number to convert + /// The base of initial number + + var result = 0; + + for(var i = (input_buffer.length - 1); i >= 0; i-- ) + result += input_buffer[(input_buffer.length - 1) - i] * Math.pow(2, input_base * i); + + return result; + } + //************************************************************************************** + function util_tobase(value, base, reserved) + { + /// Convert number from 2^10 to 2^base + /// The number to convert + /// The base for 2^base + /// Pre-defined number of bytes in output array (-1 = limited by function itself) + + reserved = reserved || (-1); + + var result = 0; + var biggest = Math.pow(2, base); + + for(var i = 1; i < 8; i++) + { + if(value < biggest) + { + var ret_buf; + + if( reserved < 0 ) + { + ret_buf = new ArrayBuffer(i); + result = i; + } + else + { + if(reserved < i) + return (new ArrayBuffer(0)); + + ret_buf = new ArrayBuffer(reserved); + + result = reserved; + } + + var ret_view = new Uint8Array(ret_buf); + + for(var j = ( i - 1 ); j >= 0; j-- ) + { + var basis = Math.pow(2, j * base); + + ret_view[ result - j - 1 ] = Math.floor( value / basis ); + value -= ( ret_view[ result - j - 1 ] ) * basis; + } + + return ret_buf; + } + + biggest *= Math.pow(2, base); + } + } + //************************************************************************************** + function util_encode_tc(value) + { + /// Encode integer value to "two complement" format + /// Value to encode + + var mod_value = (value < 0) ? (value * (-1)) : value; + var big_int = 128; + + for(var i = 1; i < 8; i++) + { + if( mod_value <= big_int ) + { + if( value < 0 ) + { + var small_int = big_int - mod_value; + + var ret_buf = util_tobase( small_int, 8, i ); + var ret_view = new Uint8Array(ret_buf); + + ret_view[ 0 ] |= 0x80; + + return ret_buf; + } + else + { + var ret_buf = util_tobase( mod_value, 8, i ); + var ret_view = new Uint8Array(ret_buf); + + if( ret_view[ 0 ] & 0x80 ) + { + var temp_buf = util_copybuf(ret_buf); + var temp_view = new Uint8Array(temp_buf); + + ret_buf = new ArrayBuffer( ret_buf.byteLength + 1 ); + ret_view = new Uint8Array(ret_buf); + + for(var k = 0; k < temp_buf.byteLength; k++) + ret_view[k + 1] = temp_view[k]; + + ret_view[0] = 0x00; + } + + return ret_buf; + } + } + + big_int *= Math.pow(2, 8); + } + + return (new ArrayBuffer(0)); + } + //************************************************************************************** + function util_decode_tc() + { + /// Decoding of "two complement" values + /// The function must be called in scope of instance of "hex_block" class ("value_hex" and "warnings" properties must be present) + + var buf = new Uint8Array(this.value_hex); + + if(this.value_hex.byteLength >= 2) + { + var condition_1 = (buf[0] == 0xFF) && (buf[1] & 0x80); + var condition_2 = (buf[0] == 0x00) && ((buf[1] & 0x80) == 0x00); + + if(condition_1 || condition_2) + this.warnings.push("Needlessly long format"); + } + + // #region Create big part of the integer + var big_int_buffer = new ArrayBuffer(this.value_hex.byteLength); + var big_int_view = new Uint8Array(big_int_buffer); + for(var i = 0; i < this.value_hex.byteLength; i++) + big_int_view[i] = 0; + + big_int_view[0] = (buf[0] & 0x80); // mask only the biggest bit + + var big_int = util_frombase(big_int_view, 8); + // #endregion + + // #region Create small part of the integer + var small_int_buffer = new ArrayBuffer(this.value_hex.byteLength); + var small_int_view = new Uint8Array(small_int_buffer); + for(var j = 0; j < this.value_hex.byteLength; j++) + small_int_view[j] = buf[j]; + + small_int_view[0] &= 0x7F; // mask biggest bit + + var small_int = util_frombase(small_int_view, 8); + // #endregion + + return (small_int - big_int); + } + //************************************************************************************** + function util_copybuf(input_buffer) + { + /// Creating a copy of input ArrayBuffer + /// ArrayBuffer for coping + + if(check_buffer_params(input_buffer, 0, input_buffer.byteLength) === false) + return (new ArrayBuffer(0)); + + var input_view = new Uint8Array(input_buffer); + + var ret_buf = new ArrayBuffer(input_buffer.byteLength); + var ret_view = new Uint8Array(ret_buf); + + for(var i = 0; i < input_buffer.byteLength; i++) + ret_view[i] = input_view[i]; + + return ret_buf; + } + //************************************************************************************** + function util_copybuf_offset(input_buffer, input_offset, input_length) + { + /// Creating a copy of input ArrayBuffer + /// ArrayBuffer for coping + + if(check_buffer_params(input_buffer, input_offset, input_length) === false) + return (new ArrayBuffer(0)); + + var input_view = new Uint8Array(input_buffer, input_offset, input_length); + + var ret_buf = new ArrayBuffer(input_length); + var ret_view = new Uint8Array(ret_buf); + + for(var i = 0; i < input_length; i++) + ret_view[i] = input_view[i]; + + return ret_buf; + } + //************************************************************************************** + function util_concatbuf(input_buf1, input_buf2) + { + /// Concatenate two ArrayBuffers + /// First ArrayBuffer (first part of concatenated array) + /// Second ArrayBuffer (second part of concatenated array) + + var input_view1 = new Uint8Array(input_buf1); + var input_view2 = new Uint8Array(input_buf2); + + var ret_buf = new ArrayBuffer(input_buf1.byteLength + input_buf2.byteLength); + var ret_view = new Uint8Array(ret_buf); + + for(var i = 0; i < input_buf1.byteLength; i++) + ret_view[i] = input_view1[i]; + + for(var j = 0; j < input_buf2.byteLength; j++) + ret_view[input_buf1.byteLength + j] = input_view2[j]; + + return ret_buf; + } + //************************************************************************************** + function check_buffer_params(input_buffer, input_offset, input_length) + { + if((input_buffer instanceof ArrayBuffer) === false) + { + this.error = "Wrong parameter: input_buffer must be \"ArrayBuffer\""; + return false; + } + + if(input_buffer.byteLength === 0) + { + this.error = "Wrong parameter: input_buffer has zero length"; + return false; + } + + if(input_offset < 0) + { + this.error = "Wrong parameter: input_offset less than zero"; + return false; + } + + if(input_length < 0) + { + this.error = "Wrong parameter: input_length less than zero"; + return false; + } + + if((input_buffer.byteLength - input_offset - input_length) < 0) + { + this.error = "End of input reached before message was fully decoded (inconsistent offset and length values)"; + return false; + } + + return true; + } + //************************************************************************************** + function to_hex_codes(input_buffer, input_offset, input_lenght) + { + if(check_buffer_params(input_buffer, input_offset, input_lenght) === false) + return ""; + + var result = ""; + + var int_buffer = new Uint8Array(input_buffer, input_offset, input_lenght); + + for(var i = 0; i < int_buffer.length; i++) + { + var str = int_buffer[i].toString(16).toUpperCase(); + result = result + ((str.length === 1) ? " 0" : " ") + str; + } + + return result; + } + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Declaration of base block class + //************************************************************************************** + local.base_block = + function() + { + /// General class of all ASN.1 blocks + + if(arguments[0] instanceof Object) + { + this.block_length = in_window.org.pkijs.getValue(arguments[0], "block_length", 0); + this.error = in_window.org.pkijs.getValue(arguments[0], "error", new String()); + this.warnings = in_window.org.pkijs.getValue(arguments[0], "warnings", new Array()); + if("value_before_decode" in arguments[0]) + this.value_before_decode = util_copybuf(arguments[0].value_before_decode); + else + this.value_before_decode = new ArrayBuffer(0); + } + else + { + this.block_length = 0; + this.error = new String(); + this.warnings = new Array(); + /// Copy of the value of incoming ArrayBuffer done before decoding + this.value_before_decode = new ArrayBuffer(0); + } + }; + //************************************************************************************** + local.base_block.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "base_block"; + }; + //************************************************************************************** + local.base_block.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + return { + block_name: local.base_block.prototype.block_name.call(this), + block_length: this.block_length, + error: this.error, + warnings: this.warnings, + value_before_decode: in_window.org.pkijs.bufferToHexCodes(this.value_before_decode, 0, this.value_before_decode.byteLength) + }; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Declaration of hex block class + //************************************************************************************** + local.hex_block = + function() + { + /// Descendant of "base_block" with internal ArrayBuffer. Need to have it in case it is not possible to store ASN.1 value in native formats + + local.base_block.call(this, arguments[0]); + + if(arguments[0] instanceof Object) + { + this.is_hex_only = in_window.org.pkijs.getValue(arguments[0], "is_hex_only", false); + if("value_hex" in arguments[0]) + this.value_hex = util_copybuf(arguments[0].value_hex); + else + this.value_hex = new ArrayBuffer(0); + } + else + { + this.is_hex_only = false; + this.value_hex = new ArrayBuffer(0); + } + }; + //************************************************************************************** + local.hex_block.prototype = new local.base_block(); + local.hex_block.constructor = local.hex_block; + //************************************************************************************** + local.hex_block.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "hex_block"; + }; + //************************************************************************************** + local.hex_block.prototype.fromBER = + function(input_buffer, input_offset, input_length) + { + /// Base function for converting block from BER encoded array of bytes + /// ASN.1 BER encoded array + /// Offset in ASN.1 BER encoded array where decoding should be started + /// Maximum length of array of bytes which can be using in this function + + // #region Basic check for parameters + if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false) + return (-1); + // #endregion + + // #region Getting Uint8Array from ArrayBuffer + var int_buffer = new Uint8Array(input_buffer, input_offset, input_length); + // #endregion + + // #region Initial checks + if(int_buffer.length == 0) + { + this.warnings.push("Zero buffer length"); + return input_offset; + } + // #endregion + + // #region Copy input buffer to internal buffer + this.value_hex = new ArrayBuffer(input_length); + var view = new Uint8Array(this.value_hex); + + for(var i = 0; i < int_buffer.length; i++) + view[i] = int_buffer[i]; + // #endregion + + this.block_length = input_length; + + return (input_offset + input_length); + }; + //************************************************************************************** + local.hex_block.prototype.toBER = + function(size_only) + { + /// Encoding of current ASN.1 block into ASN.1 encoded array (BER rules) + /// Flag that we need only a size of encoding, not a real array of bytes + + if(typeof size_only === "undefined") + size_only = false; + + if(this.is_hex_only !== true) + { + this.error = "Flag \"is_hex_only\" is not set, abort"; + return (new ArrayBuffer(0)); + } + + var ret_buf = new ArrayBuffer(this.value_hex.byteLength); + + if(size_only === true) + return ret_buf; + + var ret_view = new Uint8Array(ret_buf); + var cur_view = new Uint8Array(this.value_hex); + + for(var i = 0; i < cur_view.length; i++) + ret_view[i] = cur_view[i]; + + return ret_buf; + }; + //************************************************************************************** + local.hex_block.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.base_block.prototype.toJSON.call(this); + + _object.block_name = local.hex_block.prototype.block_name.call(this); + _object.is_hex_only = this.is_hex_only; + _object.value_hex = in_window.org.pkijs.bufferToHexCodes(this.value_hex, 0, this.value_hex.byteLength); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Declaration of identification block class + //************************************************************************************** + local.identification_block = + function() + { + /// Base class of ASN.1 "identification block" + + local.hex_block.call(this, arguments[0]); + + this.tag_class = (-1); + this.tag_number = (-1); + this.is_constructed = false; + + if(arguments[0] instanceof Object) + { + if("id_block" in arguments[0]) + { + // #region Properties from hex_block class + this.is_hex_only = in_window.org.pkijs.getValue(arguments[0].id_block, "is_hex_only", false); + this.value_hex = in_window.org.pkijs.getValue(arguments[0].id_block, "value_hex", new ArrayBuffer(0)); + // #endregion + + this.tag_class = in_window.org.pkijs.getValue(arguments[0].id_block, "tag_class", (-1)); + this.tag_number = in_window.org.pkijs.getValue(arguments[0].id_block, "tag_number", (-1)); + this.is_constructed = in_window.org.pkijs.getValue(arguments[0].id_block, "is_constructed", false); + } + } + }; + //************************************************************************************** + local.identification_block.prototype = new local.hex_block(); + local.identification_block.constructor = local.identification_block; + //************************************************************************************** + local.identification_block.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "identification_block"; + }; + //************************************************************************************** + local.identification_block.prototype.toBER = + function(size_only) + { + /// Encoding of current ASN.1 block into ASN.1 encoded array (BER rules) + /// Flag that we need only a size of encoding, not a real array of bytes + + if(typeof size_only === "undefined") + size_only = false; + + var first_octet = 0; + + switch(this.tag_class) + { + case 1: + first_octet |= 0x00; // UNIVERSAL + break; + case 2: + first_octet |= 0x40; // APPLICATION + break; + case 3: + first_octet |= 0x80; // CONTEXT-SPECIFIC + break; + case 4: + first_octet |= 0xC0; // PRIVATE + break; + default: + this.error = "Unknown tag class"; + return (new ArrayBuffer(0)); + } + + if(this.is_constructed) + first_octet |= 0x20; + + if((this.tag_number < 31) && (!this.is_hex_only)) + { + var ret_buf = new ArrayBuffer(1); + var ret_view = new Uint8Array(ret_buf); + + if(!size_only) + { + var number = this.tag_number; + number &= 0x1F; + first_octet |= number; + + ret_view[0] = first_octet; + } + + return ret_buf; + } + else + { + if(this.is_hex_only === false) + { + var encoded_buf = util_tobase(this.tag_number, 7); + var encoded_view = new Uint8Array(encoded_buf); + var size = encoded_buf.byteLength; + + var ret_buf = new ArrayBuffer(size + 1); + var ret_view = new Uint8Array(ret_buf); + + ret_view[0] = (first_octet | 0x1F); + + if(!size_only) + { + for(var i = 0; i < (size - 1) ; i++) + ret_view[i + 1] = encoded_view[i] | 0x80; + + ret_view[size] = encoded_view[size - 1]; + } + + return ret_buf; + } + else + { + var ret_buf = new ArrayBuffer(this.value_hex.byteLength + 1); + var ret_view = new Uint8Array(ret_buf); + + ret_view[0] = (first_octet | 0x1F); + + if(size_only === false) + { + var cur_view = new Uint8Array(this.value_hex); + + for(var i = 0; i < (cur_view.length - 1); i++) + ret_view[i + 1] = cur_view[i] | 0x80; + + ret_view[this.value_hex.byteLength] = cur_view[cur_view.length - 1]; + } + + return ret_buf; + } + } + }; + //************************************************************************************** + local.identification_block.prototype.fromBER = + function(input_buffer, input_offset, input_length) + { + /// Base function for converting block from BER encoded array of bytes + /// ASN.1 BER encoded array + /// Offset in ASN.1 BER encoded array where decoding should be started + /// Maximum length of array of bytes which can be using in this function + + // #region Basic check for parameters + if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false) + return (-1); + // #endregion + + // #region Getting Uint8Array from ArrayBuffer + var int_buffer = new Uint8Array(input_buffer, input_offset, input_length); + // #endregion + + // #region Initial checks + if(int_buffer.length == 0) + { + this.error = "Zero buffer length"; + return (-1); + } + // #endregion + + // #region Find tag class + var tag_class_mask = int_buffer[0] & 0xC0; + + switch(tag_class_mask) + { + case 0x00: + this.tag_class = (1); // UNIVERSAL + break; + case 0x40: + this.tag_class = (2); // APPLICATION + break; + case 0x80: + this.tag_class = (3); // CONTEXT-SPECIFIC + break; + case 0xC0: + this.tag_class = (4); // PRIVATE + break; + default: + this.error = "Unknown tag class"; + return ( -1 ); + } + // #endregion + + // #region Find it's constructed or not + this.is_constructed = (int_buffer[0] & 0x20) == 0x20; + // #endregion + + // #region Find tag number + this.is_hex_only = false; + + var tag_number_mask = int_buffer[0] & 0x1F; + + // #region Simple case (tag number < 31) + if(tag_number_mask != 0x1F) + { + this.tag_number = (tag_number_mask); + this.block_length = 1; + } + // #endregion + // #region Tag number bigger or equal to 31 + else + { + var count = 1; + + this.value_hex = new ArrayBuffer(255); + var tag_number_buffer_max_length = 255; + var int_tag_number_buffer = new Uint8Array(this.value_hex); + + while(int_buffer[count] & 0x80) + { + int_tag_number_buffer[count - 1] = int_buffer[count] & 0x7F; + count++; + + if(count >= int_buffer.length) + { + this.error = "End of input reached before message was fully decoded"; + return (-1); + } + + // #region In case if tag number length is greater than 255 bytes (rare but possible case) + if(count == tag_number_buffer_max_length) + { + tag_number_buffer_max_length += 255; + + var temp_buffer = new ArrayBuffer(tag_number_buffer_max_length); + var temp_buffer_view = new Uint8Array(temp_buffer); + + for(var i = 0; i < int_tag_number_buffer.length; i++) + temp_buffer_view[i] = int_tag_number_buffer[i]; + + this.value_hex = new ArrayBuffer(tag_number_buffer_max_length); + int_tag_number_buffer = new Uint8Array(this.value_hex); + } + // #endregion + } + + this.block_length = (count + 1); + int_tag_number_buffer[count - 1] = int_buffer[count] & 0x7F; // Write last byte to buffer + + // #region Cut buffer + var temp_buffer = new ArrayBuffer(count); + var temp_buffer_view = new Uint8Array(temp_buffer); + for(var i = 0; i < count; i++) + temp_buffer_view[i] = int_tag_number_buffer[i]; + + this.value_hex = new ArrayBuffer(count); + int_tag_number_buffer = new Uint8Array(this.value_hex); + int_tag_number_buffer.set(temp_buffer_view); + // #endregion + + // #region Try to convert long tag number to short form + if(this.block_length <= 9) + this.tag_number = util_frombase(int_tag_number_buffer, 7); + else + { + this.is_hex_only = true; + this.warnings.push("Tag too long, represented as hex-coded"); + } + // #endregion + } + // #endregion + // #endregion + + // #region Check if constructed encoding was using for primitive type + if(((this.tag_class == 1)) && + (this.is_constructed)) + { + switch(this.tag_number) + { + case 1: // BOOLEAN + case 2: // REAL + case 5: // NULL + case 6: // OBJECT IDENTIFIER + case 9: // REAL + case 14: // TIME + case 23: + case 24: + case 31: + case 32: + case 33: + case 34: + this.error = "Constructed encoding used for primitive type"; + return (-1); + default: + ; + } + } + // #endregion + + return ( input_offset + this.block_length ); // Return current offset in input buffer + }; + //************************************************************************************** + local.identification_block.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.hex_block.prototype.toJSON.call(this); + + _object.block_name = local.identification_block.prototype.block_name.call(this); + _object.tag_class = this.tag_class; + _object.tag_number = this.tag_number; + _object.is_constructed = this.is_constructed; + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Declaration of length block class + //************************************************************************************** + local.length_block = + function() + { + /// Base class of ASN.1 "length block" + + local.base_block.call(this, arguments[0]); + + this.is_indefinite_form = false; + this.long_form_used = false; + this.length = (0); + + if(arguments[0] instanceof Object) + { + if("len_block" in arguments[0]) + { + this.is_indefinite_form = in_window.org.pkijs.getValue(arguments[0].len_block, "is_indefinite_form", false); + this.long_form_used = in_window.org.pkijs.getValue(arguments[0].len_block, "long_form_used", false); + this.length = in_window.org.pkijs.getValue(arguments[0].len_block, "length", 0); + } + } + }; + //************************************************************************************** + local.length_block.prototype = new local.base_block(); + local.length_block.constructor = local.length_block; + //************************************************************************************** + local.length_block.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "length_block"; + }; + //************************************************************************************** + local.length_block.prototype.fromBER = + function(input_buffer, input_offset, input_length) + { + /// Base function for converting block from BER encoded array of bytes + /// ASN.1 BER encoded array + /// Offset in ASN.1 BER encoded array where decoding should be started + /// Maximum length of array of bytes which can be using in this function + + // #region Basic check for parameters + if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false) + return (-1); + // #endregion + + // #region Getting Uint8Array from ArrayBuffer + var int_buffer = new Uint8Array(input_buffer, input_offset, input_length); + // #endregion + + // #region Initial checks + if(int_buffer.length == 0) + { + this.error = "Zero buffer length"; + return (-1); + } + + if(int_buffer[0] == 0xFF) + { + this.error = "Length block 0xFF is reserved by standard"; + return (-1); + } + // #endregion + + // #region Check for length form type + this.is_indefinite_form = int_buffer[0] == 0x80; + // #endregion + + // #region Stop working in case of indefinite length form + if(this.is_indefinite_form == true) + { + this.block_length = 1; + return (input_offset + this.block_length); + } + // #endregion + + // #region Check is long form of length encoding using + this.long_form_used = !!(int_buffer[0] & 0x80); + // #endregion + + // #region Stop working in case of short form of length value + if(this.long_form_used == false) + { + this.length = (int_buffer[0]); + this.block_length = 1; + return (input_offset + this.block_length); + } + // #endregion + + // #region Calculate length value in case of long form + var count = int_buffer[0] & 0x7F; + + if(count > 8) // Too big length value + { + this.error = "Too big integer"; + return (-1); + } + + if((count + 1) > int_buffer.length) + { + this.error = "End of input reached before message was fully decoded"; + return (-1); + } + + var length_buffer_view = new Uint8Array(count); + + for(var i = 0; i < count; i++) + length_buffer_view[i] = int_buffer[i + 1]; + + if(length_buffer_view[count - 1] == 0x00) + this.warnings.push("Needlessly long encoded length"); + + this.length = util_frombase(length_buffer_view, 8); + + if(this.long_form_used && (this.length <= 127)) + this.warnings.push("Unneccesary usage of long length form"); + + this.block_length = count + 1; + // #endregion + + return (input_offset + this.block_length); // Return current offset in input buffer + }; + //************************************************************************************** + local.length_block.prototype.toBER = + function(size_only) + { + /// Encoding of current ASN.1 block into ASN.1 encoded array (BER rules) + /// Flag that we need only a size of encoding, not a real array of bytes + + if(typeof size_only === "undefined") + size_only = false; + + if(this.length > 127) + this.long_form_used = true; + + if(this.is_indefinite_form) + { + var ret_buf = new ArrayBuffer(1); + + if(size_only === false) + { + var ret_view = new Uint8Array(ret_buf); + ret_view[0] = 0x80; + } + + return ret_buf; + } + + if(this.long_form_used === true) + { + var encoded_buf = util_tobase(this.length, 8); + + if(encoded_buf.byteLength > 127) + { + this.error = "Too big length"; + return (new ArrayBuffer(0)); + } + + var ret_buf = new ArrayBuffer(encoded_buf.byteLength + 1); + + if(size_only === true) + return ret_buf; + + var encoded_view = new Uint8Array(encoded_buf); + var ret_view = new Uint8Array(ret_buf); + + ret_view[0] = encoded_buf.byteLength | 0x80; + + for(var i = 0; i < encoded_buf.byteLength; i++) + ret_view[i + 1] = encoded_view[i]; + + return ret_buf; + } + else + { + var ret_buf = new ArrayBuffer(1); + + if(size_only === false) + { + var ret_view = new Uint8Array(ret_buf); + + ret_view[0] = this.length; + } + + return ret_buf; + } + + return (new ArrayBuffer(0)); + }; + //************************************************************************************** + local.length_block.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.base_block.prototype.toJSON.call(this); + + _object.block_name = local.length_block.prototype.block_name.call(this); + _object.is_indefinite_form = this.is_indefinite_form; + _object.long_form_used = this.long_form_used; + _object.length = this.length; + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Declaration of value block class + //************************************************************************************** + local.value_block = + function() + { + /// Generic class of ASN.1 "value block" + local.base_block.call(this, arguments[0]); + }; + //************************************************************************************** + local.value_block.prototype = new local.base_block(); + local.value_block.constructor = local.value_block; + //************************************************************************************** + local.value_block.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "value_block"; + }; + //************************************************************************************** + local.value_block.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.base_block.prototype.toJSON.call(this); + + _object.block_name = local.value_block.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Declaration of basic ASN.1 block class + //************************************************************************************** + in_window.org.pkijs.asn1.ASN1_block = + function() + { + /// Base class of ASN.1 block (identification block + length block + value block) + + local.base_block.call(this, arguments[0]); + + if(arguments[0] instanceof Object) + { + this.name = in_window.org.pkijs.getValue(arguments[0], "name", ""); + this.optional = in_window.org.pkijs.getValue(arguments[0], "optional", false); + + if("primitive_schema" in arguments[0]) + this.primitive_schema = arguments[0].primitive_schema; + } + + this.id_block = new local.identification_block(arguments[0]); + this.len_block = new local.length_block(arguments[0]); + this.value_block = new local.value_block(arguments[0]); + }; + //************************************************************************************** + in_window.org.pkijs.asn1.ASN1_block.prototype = new local.base_block(); + in_window.org.pkijs.asn1.ASN1_block.constructor = in_window.org.pkijs.asn1.ASN1_block; + //************************************************************************************** + in_window.org.pkijs.asn1.ASN1_block.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "ASN1_block"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.ASN1_block.prototype.fromBER = + function(input_buffer, input_offset, input_length) + { + /// Base function for converting block from BER encoded array of bytes + /// ASN.1 BER encoded array + /// Offset in ASN.1 BER encoded array where decoding should be started + /// Maximum length of array of bytes which can be using in this function + + var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length); + if(result_offset == (-1)) + { + this.error = this.value_block.error; + return result_offset; + } + + if(this.id_block.error.length == 0) + this.block_length += this.id_block.block_length; + + if(this.len_block.error.length == 0) + this.block_length += this.len_block.block_length; + + if(this.value_block.error.length == 0) + this.block_length += this.value_block.block_length; + + return result_offset; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.ASN1_block.prototype.toBER = + function(size_only) + { + /// Encoding of current ASN.1 block into ASN.1 encoded array (BER rules) + /// Flag that we need only a size of encoding, not a real array of bytes + + if(typeof size_only === "undefined") + size_only = false; + + var ret_buf; + + var id_block_buf = this.id_block.toBER(size_only); + var value_block_size_buf = this.value_block.toBER(true); + + this.len_block.length = value_block_size_buf.byteLength; + var len_block_buf = this.len_block.toBER(size_only); + + ret_buf = util_concatbuf(id_block_buf, len_block_buf); + + var value_block_buf; + + if(size_only === false) + value_block_buf = this.value_block.toBER(size_only); + else + value_block_buf = new ArrayBuffer(this.len_block.length); + + ret_buf = util_concatbuf(ret_buf, value_block_buf); + + if(this.len_block.is_indefinite_form === true) + { + var indef_buf = new ArrayBuffer(2); + + if(size_only === false) + { + var indef_view = new Uint8Array(indef_buf); + + indef_view[0] = 0x00; + indef_view[1] = 0x00; + } + + ret_buf = util_concatbuf(ret_buf, indef_buf); + } + + return ret_buf; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.base_block.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.ASN1_block.prototype.block_name.call(this); + _object.id_block = this.id_block.toJSON(); + _object.len_block = this.len_block.toJSON(); + _object.value_block = this.value_block.toJSON(); + + if("name" in this) + _object.name = this.name; + if("optional" in this) + _object.optional = this.optional; + if("primitive_schema" in this) + _object.primitive_schema = this.primitive_schema.toJSON(); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Declaration of basic block for all PRIMITIVE types + //************************************************************************************** + local.ASN1_PRIMITIVE_value_block = + function() + { + /// Base class of ASN.1 value block for primitive values (non-constructive encoding) + + local.value_block.call(this, arguments[0]); + + if(arguments[0] instanceof Object) + { + // #region Variables from "hex_block" class + if("value_hex" in arguments[0]) + this.value_hex = util_copybuf(arguments[0].value_hex); + else + this.value_hex = new ArrayBuffer(0); + + this.is_hex_only = in_window.org.pkijs.getValue(arguments[0], "is_hex_only", true); + // #endregion + } + else + { + // #region Variables from "hex_block" class + this.value_hex = new ArrayBuffer(0); + this.is_hex_only = true; + // #endregion + } + }; + //************************************************************************************** + local.ASN1_PRIMITIVE_value_block.prototype = new local.value_block(); + local.ASN1_PRIMITIVE_value_block.constructor = local.ASN1_PRIMITIVE_value_block; + //************************************************************************************** + local.ASN1_PRIMITIVE_value_block.prototype.fromBER = + function(input_buffer, input_offset, input_length) + { + /// Base function for converting block from BER encoded array of bytes + /// ASN.1 BER encoded array + /// Offset in ASN.1 BER encoded array where decoding should be started + /// Maximum length of array of bytes which can be using in this function + + // #region Basic check for parameters + if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false) + return (-1); + // #endregion + + // #region Getting Uint8Array from ArrayBuffer + var int_buffer = new Uint8Array(input_buffer, input_offset, input_length); + // #endregion + + // #region Initial checks + if(int_buffer.length == 0) + { + this.warnings.push("Zero buffer length"); + return input_offset; + } + // #endregion + + // #region Copy input buffer into internal buffer + this.value_hex = new ArrayBuffer(int_buffer.length); + var value_hex_view = new Uint8Array(this.value_hex); + + for(var i = 0; i < int_buffer.length; i++) + value_hex_view[i] = int_buffer[i]; + // #endregion + + this.block_length = input_length; + + return (input_offset + input_length); + }; + //************************************************************************************** + local.ASN1_PRIMITIVE_value_block.prototype.toBER = + function(size_only) + { + /// Encoding of current ASN.1 block into ASN.1 encoded array (BER rules) + /// Flag that we need only a size of encoding, not a real array of bytes + + return util_copybuf(this.value_hex); + }; + //************************************************************************************** + local.ASN1_PRIMITIVE_value_block.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "ASN1_PRIMITIVE_value_block"; + }; + //************************************************************************************** + local.ASN1_PRIMITIVE_value_block.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.value_block.prototype.toJSON.call(this); + + _object.block_name = local.ASN1_PRIMITIVE_value_block.prototype.block_name.call(this); + _object.value_hex = in_window.org.pkijs.bufferToHexCodes(this.value_hex, 0, this.value_hex.byteLength); + _object.is_hex_only = this.is_hex_only; + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.ASN1_PRIMITIVE = + function() + { + /// Base class of ASN.1 block for primitive values (non-constructive encoding) + + in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); + + this.id_block.is_constructed = false; + this.value_block = new local.ASN1_PRIMITIVE_value_block(arguments[0]); + }; + //************************************************************************************** + in_window.org.pkijs.asn1.ASN1_PRIMITIVE.prototype = new in_window.org.pkijs.asn1.ASN1_block(); + in_window.org.pkijs.asn1.ASN1_PRIMITIVE.constructor = in_window.org.pkijs.asn1.ASN1_PRIMITIVE; + //************************************************************************************** + in_window.org.pkijs.asn1.ASN1_PRIMITIVE.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "PRIMITIVE"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.ASN1_PRIMITIVE.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.ASN1_PRIMITIVE.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Declaration of basic block for all CONSTRUCTED types + //************************************************************************************** + local.ASN1_CONSTRUCTED_value_block = + function() + { + /// Base class of ASN.1 value block for constructive values (constructive encoding) + + local.value_block.call(this, arguments[0]); + + if(arguments[0] instanceof Object) + { + this.value = in_window.org.pkijs.getValue(arguments[0], "value", new Array()); + this.is_indefinite_form = in_window.org.pkijs.getValue(arguments[0], "is_indefinite_form", false); + } + else + { + this.value = new Array(); + this.is_indefinite_form = false; + } + }; + //************************************************************************************** + local.ASN1_CONSTRUCTED_value_block.prototype = new local.value_block(); + local.ASN1_CONSTRUCTED_value_block.constructor = local.ASN1_CONSTRUCTED_value_block; + //************************************************************************************** + local.ASN1_CONSTRUCTED_value_block.prototype.fromBER = + function(input_buffer, input_offset, input_length) + { + /// Base function for converting block from BER encoded array of bytes + /// ASN.1 BER encoded array + /// Offset in ASN.1 BER encoded array where decoding should be started + /// Maximum length of array of bytes which can be using in this function + + // #region Store initial offset and length + var initial_offset = input_offset; + var initial_length = input_length; + // #endregion + + // #region Basic check for parameters + if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false) + return (-1); + // #endregion + + // #region Getting Uint8Array from ArrayBuffer + var int_buffer = new Uint8Array(input_buffer, input_offset, input_length); + // #endregion + + // #region Initial checks + if(int_buffer.length == 0) + { + this.warnings.push("Zero buffer length"); + return input_offset; + } + // #endregion + + // #region Aux function + function check_len(_indefinite_length, _length) + { + if(_indefinite_length == true) + return 1; + + return _length; + } + // #endregion + + var current_offset = input_offset; + + while(check_len(this.is_indefinite_form, input_length) > 0) + { + var return_object = fromBER_raw(input_buffer, current_offset, input_length); + if(return_object.offset == (-1)) + { + this.error = return_object.result.error; + this.warnings.concat(return_object.result.warnings); + return (-1); + } + + current_offset = return_object.offset; + + this.block_length += return_object.result.block_length; + input_length -= return_object.result.block_length; + + this.value.push(return_object.result); + + if((this.is_indefinite_form == true) && (return_object.result.block_name() == in_window.org.pkijs.asn1.EOC.prototype.block_name())) + break; + } + + if(this.is_indefinite_form == true) + { + if(this.value[this.value.length - 1].block_name() == in_window.org.pkijs.asn1.EOC.prototype.block_name()) + this.value.pop(); + else + this.warnings.push("No EOC block encoded"); + } + + // #region Copy "input_buffer" to "value_before_decode" + this.value_before_decode = util_copybuf_offset(input_buffer, initial_offset, initial_length); + // #endregion + + return current_offset; + }; + //************************************************************************************** + local.ASN1_CONSTRUCTED_value_block.prototype.toBER = + function(size_only) + { + /// Encoding of current ASN.1 block into ASN.1 encoded array (BER rules) + /// Flag that we need only a size of encoding, not a real array of bytes + + if(typeof size_only === "undefined") + size_only = false; + + var ret_buf = new ArrayBuffer(0); + + for(var i = 0; i < this.value.length; i++) + { + var value_buf = this.value[i].toBER(size_only); + ret_buf = util_concatbuf(ret_buf, value_buf); + } + + return ret_buf; + }; + //************************************************************************************** + local.ASN1_CONSTRUCTED_value_block.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "ASN1_CONSTRUCTED_value_block"; + }; + //************************************************************************************** + local.ASN1_CONSTRUCTED_value_block.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.value_block.prototype.toJSON.call(this); + + _object.block_name = local.ASN1_CONSTRUCTED_value_block.prototype.block_name.call(this); + _object.is_indefinite_form = this.is_indefinite_form; + _object.value = new Array(); + for(var i = 0; i < this.value.length; i++) + _object.value.push(this.value[i].toJSON()); + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.ASN1_CONSTRUCTED = + function() + { + /// Base class of ASN.1 block for constructive values (constructive encoding) + + in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); + + this.id_block.is_constructed = true; + this.value_block = new local.ASN1_CONSTRUCTED_value_block(arguments[0]); + }; + //************************************************************************************** + in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype = new in_window.org.pkijs.asn1.ASN1_block(); + in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.constructor = in_window.org.pkijs.asn1.ASN1_CONSTRUCTED; + //************************************************************************************** + in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "CONSTRUCTED"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype.fromBER = + function(input_buffer, input_offset, input_length) + { + /// Base function for converting block from BER encoded array of bytes + /// ASN.1 BER encoded array + /// Offset in ASN.1 BER encoded array where decoding should be started + /// Maximum length of array of bytes which can be using in this function + + this.value_block.is_indefinite_form = this.len_block.is_indefinite_form; + + var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length); + if(result_offset == (-1)) + { + this.error = this.value_block.error; + return result_offset; + } + + if(this.id_block.error.length == 0) + this.block_length += this.id_block.block_length; + + if(this.len_block.error.length == 0) + this.block_length += this.len_block.block_length; + + if(this.value_block.error.length == 0) + this.block_length += this.value_block.block_length; + + return result_offset; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Declaration of ASN.1 EOC type class + //************************************************************************************** + local.EOC_value_block = + function() + { + local.value_block.call(this, arguments[0]); + }; + //************************************************************************************** + local.EOC_value_block.prototype = new local.value_block(); + local.EOC_value_block.constructor = local.EOC_value_block; + //************************************************************************************** + local.EOC_value_block.prototype.fromBER = + function(input_buffer, input_offset, input_length) + { + /// Base function for converting block from BER encoded array of bytes + /// ASN.1 BER encoded array + /// Offset in ASN.1 BER encoded array where decoding should be started + /// Maximum length of array of bytes which can be using in this function + + // #region There is no "value block" for EOC type and we need to return the same offset + return input_offset; + // #endregion + }; + //************************************************************************************** + local.EOC_value_block.prototype.toBER = + function(size_only) + { + /// Encoding of current ASN.1 block into ASN.1 encoded array (BER rules) + /// Flag that we need only a size of encoding, not a real array of bytes + + return (new ArrayBuffer(0)); + }; + //************************************************************************************** + local.EOC_value_block.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "EOC_value_block"; + }; + //************************************************************************************** + local.EOC_value_block.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.value_block.prototype.toJSON.call(this); + + _object.block_name = local.EOC_value_block.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.EOC = + function() + { + in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); + + this.value_block = new local.EOC_value_block(); + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 0; // EOC + }; + //************************************************************************************** + in_window.org.pkijs.asn1.EOC.prototype = new in_window.org.pkijs.asn1.ASN1_block(); + in_window.org.pkijs.asn1.EOC.constructor = local.EOC_value_block; + //************************************************************************************** + in_window.org.pkijs.asn1.EOC.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "END_OF_CONTENT"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.EOC.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.EOC.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Declaration of ASN.1 BOOLEAN type class + //************************************************************************************** + local.BOOLEAN_value_block = + function() + { + local.value_block.call(this, arguments[0]); + + if(arguments[0] instanceof Object) + { + this.value = in_window.org.pkijs.getValue(arguments[0], "value", false); + + // #region Variables from hex_block class + this.is_hex_only = in_window.org.pkijs.getValue(arguments[0], "is_hex_only", false); + if("value_hex" in arguments[0]) + this.value_hex = util_copybuf(arguments[0].value_hex); + else + { + this.value_hex = new ArrayBuffer(1); + if(this.value === true) + { + var view = new Uint8Array(this.value_hex); + view[0] = 0xFF; + } + } + // #endregion + } + else + { + this.value = false; + + // #region Variables from hex_block class + this.is_hex_only = false; + this.value_hex = new ArrayBuffer(1); + // #endregion + } + }; + //************************************************************************************** + local.BOOLEAN_value_block.prototype = new local.value_block(); + local.BOOLEAN_value_block.constructor = local.BOOLEAN_value_block; + //************************************************************************************** + local.BOOLEAN_value_block.prototype.fromBER = + function(input_buffer, input_offset, input_length) + { + /// Base function for converting block from BER encoded array of bytes + /// ASN.1 BER encoded array + /// Offset in ASN.1 BER encoded array where decoding should be started + /// Maximum length of array of bytes which can be using in this function + + // #region Basic check for parameters + if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false) + return (-1); + // #endregion + + // #region Getting Uint8Array from ArrayBuffer + var int_buffer = new Uint8Array(input_buffer, input_offset, input_length); + // #endregion + + if(input_length > 1) + this.warnings.push("BOOLEAN value encoded in more then 1 octet"); + + this.value = int_buffer[0] != 0x00; + + this.is_hex_only = true; + + // #region Copy input buffer to internal array + this.value_hex = new ArrayBuffer(int_buffer.length); + var view = new Uint8Array(this.value_hex); + + for(var i = 0; i < int_buffer.length; i++) + view[i] = int_buffer[i]; + // #endregion + + this.block_length = input_length; + + return (input_offset + input_length); + }; + //************************************************************************************** + local.BOOLEAN_value_block.prototype.toBER = + function(size_only) + { + /// Encoding of current ASN.1 block into ASN.1 encoded array (BER rules) + /// Flag that we need only a size of encoding, not a real array of bytes + + if(typeof size_only === "undefined") + size_only = false; + + return this.value_hex; + }; + //************************************************************************************** + local.BOOLEAN_value_block.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "BOOLEAN_value_block"; + }; + //************************************************************************************** + local.BOOLEAN_value_block.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.value_block.prototype.toJSON.call(this); + + _object.block_name = local.BOOLEAN_value_block.prototype.block_name.call(this); + _object.value = this.value; + _object.is_hex_only = this.is_hex_only; + _object.value_hex = in_window.org.pkijs.bufferToHexCodes(this.value_hex, 0, this.value_hex.byteLength); + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.BOOLEAN = + function() + { + in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); + + this.value_block = new local.BOOLEAN_value_block(arguments[0]); + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 1; // BOOLEAN + }; + //************************************************************************************** + in_window.org.pkijs.asn1.BOOLEAN.prototype = new in_window.org.pkijs.asn1.ASN1_block(); + in_window.org.pkijs.asn1.BOOLEAN.constructor = local.BOOLEAN_value_block; + //************************************************************************************** + in_window.org.pkijs.asn1.BOOLEAN.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "BOOLEAN"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.BOOLEAN.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.BOOLEAN.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Declaration of ASN.1 SEQUENCE and SET type classes + //************************************************************************************** + in_window.org.pkijs.asn1.SEQUENCE = + function() + { + in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.call(this, arguments[0]); + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 16; // SEQUENCE + }; + //************************************************************************************** + in_window.org.pkijs.asn1.SEQUENCE.prototype = new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED(); + in_window.org.pkijs.asn1.SEQUENCE.constructor = in_window.org.pkijs.asn1.SEQUENCE; + //************************************************************************************** + in_window.org.pkijs.asn1.SEQUENCE.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "SEQUENCE"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.SEQUENCE.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.SEQUENCE.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.SET = + function() + { + in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.call(this, arguments[0]); + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 17; // SET + }; + //************************************************************************************** + in_window.org.pkijs.asn1.SET.prototype = new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED(); + in_window.org.pkijs.asn1.SET.constructor = in_window.org.pkijs.asn1.SET; + //************************************************************************************** + in_window.org.pkijs.asn1.SET.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "SET"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.SET.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.SET.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Declaration of ASN.1 NULL type class + //************************************************************************************** + in_window.org.pkijs.asn1.NULL = + function() + { + in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 5; // NULL + }; + //************************************************************************************** + in_window.org.pkijs.asn1.NULL.prototype = new in_window.org.pkijs.asn1.ASN1_block(); + in_window.org.pkijs.asn1.NULL.constructor = in_window.org.pkijs.asn1.NULL; + //************************************************************************************** + in_window.org.pkijs.asn1.NULL.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "NULL"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.NULL.prototype.fromBER = + function(input_buffer, input_offset, input_length) + { + /// Base function for converting block from BER encoded array of bytes + /// ASN.1 BER encoded array + /// Offset in ASN.1 BER encoded array where decoding should be started + /// Maximum length of array of bytes which can be using in this function + + if(this.len_block.length > 0) + this.warnings.push("Non-zero length of value block for NULL type"); + + if(this.id_block.error.length === 0) + this.block_length += this.id_block.block_length; + + if(this.len_block.error.length === 0) + this.block_length += this.len_block.block_length; + + this.block_length += input_length; + + return (input_offset + input_length); + }; + //************************************************************************************** + in_window.org.pkijs.asn1.NULL.prototype.toBER = + function(size_only) + { + /// Encoding of current ASN.1 block into ASN.1 encoded array (BER rules) + /// Flag that we need only a size of encoding, not a real array of bytes + + if(typeof size_only === "undefined") + size_only = false; + + var ret_buf = new ArrayBuffer(2); + + if(size_only === true) + return ret_buf; + + var ret_view = new Uint8Array(ret_buf); + ret_view[0] = 0x05; + ret_view[1] = 0x00; + + return ret_buf; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.NULL.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.NULL.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Declaration of ASN.1 OCTETSTRING type class + //************************************************************************************** + local.OCTETSTRING_value_block = + function() + { + /// + /// + /// + /// Value for the OCTETSTRING may be as hex, as well as a constructed value. + /// Constructed values consists of other OCTETSTRINGs + + local.ASN1_CONSTRUCTED_value_block.call(this, arguments[0]); + + if(arguments[0] instanceof Object) + { + this.is_constructed = in_window.org.pkijs.getValue(arguments[0], "is_constructed", false); + + // #region Variables from hex_block type + this.is_hex_only = in_window.org.pkijs.getValue(arguments[0], "is_hex_only", false); + if("value_hex" in arguments[0]) + this.value_hex = util_copybuf(arguments[0].value_hex); + else + this.value_hex = new ArrayBuffer(0); + // #endregion + } + else + { + this.is_constructed = false; + + // #region Variables from hex_block type + this.is_hex_only = false; + this.value_hex = new ArrayBuffer(0); + // #endregion + } + }; + //************************************************************************************** + local.OCTETSTRING_value_block.prototype = new local.ASN1_CONSTRUCTED_value_block(); + local.OCTETSTRING_value_block.constructor = local.OCTETSTRING_value_block; + //************************************************************************************** + local.OCTETSTRING_value_block.prototype.fromBER = + function(input_buffer, input_offset, input_length) + { + /// Base function for converting block from BER encoded array of bytes + /// ASN.1 BER encoded array + /// Offset in ASN.1 BER encoded array where decoding should be started + /// Maximum length of array of bytes which can be using in this function + + var result_offset = 0; + + if(this.is_constructed == true) + { + this.is_hex_only = false; + + result_offset = local.ASN1_CONSTRUCTED_value_block.prototype.fromBER.call(this, input_buffer, input_offset, input_length); + if(result_offset == (-1)) + return result_offset; + + for(var i = 0; i < this.value.length; i++) + { + var current_block_name = this.value[i].block_name(); + + if(current_block_name == in_window.org.pkijs.asn1.EOC.prototype.block_name()) + { + if(this.is_indefinite_form == true) + break; + else + { + this.error = "EOC is unexpected, OCTET STRING may consists of OCTET STRINGs only"; + return (-1); + } + } + + if(current_block_name != in_window.org.pkijs.asn1.OCTETSTRING.prototype.block_name()) + { + this.error = "OCTET STRING may consists of OCTET STRINGs only"; + return (-1); + } + } + } + else + { + this.is_hex_only = true; + + result_offset = local.hex_block.prototype.fromBER.call(this, input_buffer, input_offset, input_length); + this.block_length = input_length; + } + + return result_offset; + }; + //************************************************************************************** + local.OCTETSTRING_value_block.prototype.toBER = + function(size_only) + { + /// Encoding of current ASN.1 block into ASN.1 encoded array (BER rules) + /// Flag that we need only a size of encoding, not a real array of bytes + + if(typeof size_only === "undefined") + size_only = false; + + if(this.is_constructed === true) + return local.ASN1_CONSTRUCTED_value_block.prototype.toBER.call(this, size_only); + else + { + var ret_buf = new ArrayBuffer(this.value_hex.byteLength); + + if(size_only === true) + return ret_buf; + + if(this.value_hex.byteLength == 0) + return ret_buf; + + ret_buf = util_copybuf(this.value_hex); + + return ret_buf; + } + + return (new ArrayBuffer(0)); + }; + //************************************************************************************** + local.OCTETSTRING_value_block.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "OCTETSTRING_value_block"; + }; + //************************************************************************************** + local.OCTETSTRING_value_block.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.ASN1_CONSTRUCTED_value_block.prototype.toJSON.call(this); + + _object.block_name = local.OCTETSTRING_value_block.prototype.block_name.call(this); + _object.is_constructed = this.is_constructed; + _object.is_hex_only = this.is_hex_only; + _object.value_hex = in_window.org.pkijs.bufferToHexCodes(this.value_hex, 0, this.value_hex.byteLength); + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.OCTETSTRING = + function() + { + in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); + + this.value_block = new local.OCTETSTRING_value_block(arguments[0]); + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 4; // OCTETSTRING + }; + //************************************************************************************** + in_window.org.pkijs.asn1.OCTETSTRING.prototype = new in_window.org.pkijs.asn1.ASN1_block(); + in_window.org.pkijs.asn1.OCTETSTRING.constructor = in_window.org.pkijs.asn1.OCTETSTRING; + //************************************************************************************** + in_window.org.pkijs.asn1.OCTETSTRING.prototype.fromBER = + function(input_buffer, input_offset, input_length) + { + /// Base function for converting block from BER encoded array of bytes + /// ASN.1 BER encoded array + /// Offset in ASN.1 BER encoded array where decoding should be started + /// Maximum length of array of bytes which can be using in this function + + this.value_block.is_constructed = this.id_block.is_constructed; + this.value_block.is_indefinite_form = this.len_block.is_indefinite_form; + + // #region Ability to encode empty OCTET STRING + if(input_length == 0) + { + if(this.id_block.error.length == 0) + this.block_length += this.id_block.block_length; + + if(this.len_block.error.length == 0) + this.block_length += this.len_block.block_length; + + return input_offset; + } + // #endregion + + return in_window.org.pkijs.asn1.ASN1_block.prototype.fromBER.call(this, input_buffer, input_offset, input_length); + }; + //************************************************************************************** + in_window.org.pkijs.asn1.OCTETSTRING.prototype.block_name = + function() + { + return "OCTETSTRING"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.OCTETSTRING.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.OCTETSTRING.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.OCTETSTRING.prototype.isEqual = + function(octetString) + { + /// + /// The OCTETSTRING to compare with + + // #region Check input type + if((octetString instanceof in_window.org.pkijs.asn1.OCTETSTRING) == false) + return false; + // #endregion + + // #region Compare two JSON strings + if(JSON.stringify(this) != JSON.stringify(octetString)) + return false; + // #endregion + + return true; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Declaration of ASN.1 BITSTRING type class + //************************************************************************************** + local.BITSTRING_value_block = + function() + { + local.ASN1_CONSTRUCTED_value_block.call(this, arguments[0]); + + if(arguments[0] instanceof Object) + { + this.unused_bits = in_window.org.pkijs.getValue(arguments[0], "unused_bits", 0); + this.is_constructed = in_window.org.pkijs.getValue(arguments[0], "is_constructed", false); + + // #region Variables from hex_block type + this.is_hex_only = in_window.org.pkijs.getValue(arguments[0], "is_hex_only", false); + + if("value_hex" in arguments[0]) + this.value_hex = util_copybuf(arguments[0].value_hex); + else + this.value_hex = new ArrayBuffer(0); + + this.block_length = this.value_hex.byteLength; + // #endregion + } + else + { + this.unused_bits = 0; + this.is_constructed = false; + + // #region Variables from hex_block type + this.is_hex_only = false; + this.value_hex = new ArrayBuffer(0); + // #endregion + } + }; + //************************************************************************************** + local.BITSTRING_value_block.prototype = new local.ASN1_CONSTRUCTED_value_block(); + local.BITSTRING_value_block.constructor = local.BITSTRING_value_block; + //************************************************************************************** + local.BITSTRING_value_block.prototype.fromBER = + function(input_buffer, input_offset, input_length) + { + /// Base function for converting block from BER encoded array of bytes + /// ASN.1 BER encoded array + /// Offset in ASN.1 BER encoded array where decoding should be started + /// Maximum length of array of bytes which can be using in this function + + // #region Ability to decode zero-length BITSTRING value + if(input_length == 0) + return input_offset; + // #endregion + + var result_offset = (-1); + + // #region If the BISTRING supposed to be a constructed value + if(this.is_constructed == true) + { + result_offset = local.ASN1_CONSTRUCTED_value_block.prototype.fromBER.call(this, input_buffer, input_offset, input_length); + if(result_offset == (-1)) + return result_offset; + + for(var i = 0; i < this.value.length; i++) + { + var current_block_name = this.value[i].block_name(); + + if(current_block_name == in_window.org.pkijs.asn1.EOC.prototype.block_name()) + { + if(this.is_indefinite_form == true) + break; + else + { + this.error = "EOC is unexpected, BIT STRING may consists of BIT STRINGs only"; + return (-1); + } + } + + if(current_block_name != in_window.org.pkijs.asn1.BITSTRING.prototype.block_name()) + { + this.error = "BIT STRING may consists of BIT STRINGs only"; + return (-1); + } + + if((this.unused_bits > 0) && (this.value[i].unused_bits > 0)) + { + this.error = "Usign of \"unused bits\" inside constructive BIT STRING allowed for least one only"; + return (-1); + } + else + { + this.unused_bits = this.value[i].unused_bits; + if(this.unused_bits > 7) + { + this.error = "Unused bits for BITSTRING must be in range 0-7"; + return (-1); + } + } + } + + return result_offset; + } + // #endregion + // #region If the BITSTRING supposed to be a primitive value + else + { + // #region Basic check for parameters + if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false) + return (-1); + // #endregion + + var int_buffer = new Uint8Array(input_buffer, input_offset, input_length); + + this.unused_bits = int_buffer[0]; + if(this.unused_bits > 7) + { + this.error = "Unused bits for BITSTRING must be in range 0-7"; + return (-1); + } + + // #region Copy input buffer to internal buffer + this.value_hex = new ArrayBuffer(int_buffer.length - 1); + var view = new Uint8Array(this.value_hex); + for(var i = 0; i < (input_length - 1) ; i++) + view[i] = int_buffer[i + 1]; + // #endregion + + this.block_length = int_buffer.length; + + return (input_offset + input_length); + } + // #endregion + }; + //************************************************************************************** + local.BITSTRING_value_block.prototype.toBER = + function(size_only) + { + /// Encoding of current ASN.1 block into ASN.1 encoded array (BER rules) + /// Flag that we need only a size of encoding, not a real array of bytes + + if(typeof size_only === "undefined") + size_only = false; + + if(this.is_constructed === true) + return local.ASN1_CONSTRUCTED_value_block.prototype.toBER.call(this, size_only); + else + { + if(size_only === true) + return (new ArrayBuffer(this.value_hex.byteLength + 1)); + + if(this.value_hex.byteLength == 0) + return (new ArrayBuffer(0)); + + var cur_view = new Uint8Array(this.value_hex); + + var ret_buf = new ArrayBuffer(this.value_hex.byteLength + 1); + var ret_view = new Uint8Array(ret_buf); + + ret_view[0] = this.unused_bits; + + for(var i = 0; i < this.value_hex.byteLength; i++) + ret_view[i + 1] = cur_view[i]; + + return ret_buf; + } + + return (new ArrayBuffer(0)); + }; + //************************************************************************************** + local.BITSTRING_value_block.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "BITSTRING_value_block"; + }; + //************************************************************************************** + local.BITSTRING_value_block.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.ASN1_CONSTRUCTED_value_block.prototype.toJSON.call(this); + + _object.block_name = local.BITSTRING_value_block.prototype.block_name.call(this); + _object.unused_bits = this.unused_bits; + _object.is_constructed = this.is_constructed; + _object.is_hex_only = this.is_hex_only; + _object.value_hex = in_window.org.pkijs.bufferToHexCodes(this.value_hex, 0, this.value_hex.byteLength); + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.BITSTRING = + function() + { + in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); + + this.value_block = new local.BITSTRING_value_block(arguments[0]); + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 3; // BITSTRING + }; + //************************************************************************************** + in_window.org.pkijs.asn1.BITSTRING.prototype = new in_window.org.pkijs.asn1.ASN1_block(); + in_window.org.pkijs.asn1.BITSTRING.constructor = in_window.org.pkijs.asn1.BITSTRING; + //************************************************************************************** + in_window.org.pkijs.asn1.BITSTRING.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "BITSTRING"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.BITSTRING.prototype.fromBER = + function(input_buffer, input_offset, input_length) + { + /// Base function for converting block from BER encoded array of bytes + /// ASN.1 BER encoded array + /// Offset in ASN.1 BER encoded array where decoding should be started + /// Maximum length of array of bytes which can be using in this function + + // #region Ability to encode empty BITSTRING + if(input_length == 0) + return input_offset; + // #endregion + + this.value_block.is_constructed = this.id_block.is_constructed; + this.value_block.is_indefinite_form = this.len_block.is_indefinite_form; + + return in_window.org.pkijs.asn1.ASN1_block.prototype.fromBER.call(this, input_buffer, input_offset, input_length); + }; + //************************************************************************************** + in_window.org.pkijs.asn1.BITSTRING.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.BITSTRING.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Declaration of ASN.1 INTEGER type class + //************************************************************************************** + local.INTEGER_value_block = + function() + { + local.value_block.call(this, arguments[0]); + + if(arguments[0] instanceof Object) + { + this.value_dec = in_window.org.pkijs.getValue(arguments[0], "value", 0); + + // #region Variables from hex_block type + this.is_hex_only = in_window.org.pkijs.getValue(arguments[0], "is_hex_only", false); + if("value_hex" in arguments[0]) + { + this.value_hex = util_copybuf(arguments[0].value_hex); + + if(this.value_hex.byteLength >= 4) // Dummy's protection + this.is_hex_only = true; + else + this.value_dec = util_decode_tc.call(this); + } + else + this.value_hex = util_encode_tc(this.value_dec); + // #endregion + } + else + { + this.value_dec = 0; + + // #region Variables from hex_block type + this.is_hex_only = false; + this.value_hex = new ArrayBuffer(0); + // #endregion + } + }; + //************************************************************************************** + local.INTEGER_value_block.prototype = new local.value_block(); + local.INTEGER_value_block.constructor = local.INTEGER_value_block; + //************************************************************************************** + local.INTEGER_value_block.prototype.fromBER = + function(input_buffer, input_offset, input_length) + { + /// Base function for converting block from BER encoded array of bytes + /// ASN.1 BER encoded array + /// Offset in ASN.1 BER encoded array where decoding should be started + /// Maximum length of array of bytes which can be using in this function + + var result_offset = local.hex_block.prototype.fromBER.call(this, input_buffer, input_offset, input_length); + if(result_offset == (-1)) + return result_offset; + + if(this.value_hex.byteLength > 4) // In JavaScript we can effectively work with 32-bit integers only + { + this.warnings.push("Too big INTEGER for decoding, hex only"); + this.is_hex_only = true; + } + else + this.value_dec = util_decode_tc.call(this); + + this.block_length = input_length; + + return (input_offset + input_length); + }; + //************************************************************************************** + local.INTEGER_value_block.prototype.toBER = + function(size_only) + { + /// Encoding of current ASN.1 block into ASN.1 encoded array (BER rules) + /// Flag that we need only a size of encoding, not a real array of bytes + + if(typeof size_only === "undefined") + size_only = false; + + if(this.is_hex_only === false) + { + var encoded_buf = util_encode_tc(this.value_dec); + if(encoded_buf.byteLength == 0) + { + this.error = "Error during encoding INTEGER value"; + return (new ArrayBuffer(0)); + } + + return util_copybuf(encoded_buf); + } + else + return util_copybuf(this.value_hex); + + return (new ArrayBuffer(0)); + }; + //************************************************************************************** + local.INTEGER_value_block.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "INTEGER_value_block"; + }; + //************************************************************************************** + local.INTEGER_value_block.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.value_block.prototype.toJSON.call(this); + + _object.block_name = local.INTEGER_value_block.prototype.block_name.call(this); + _object.value_dec = this.value_dec; + _object.is_hex_only = this.is_hex_only; + _object.value_hex = in_window.org.pkijs.bufferToHexCodes(this.value_hex, 0, this.value_hex.byteLength); + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.INTEGER = + function() + { + in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); + + this.value_block = new local.INTEGER_value_block(arguments[0]); + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 2; // INTEGER + }; + //************************************************************************************** + in_window.org.pkijs.asn1.INTEGER.prototype = new in_window.org.pkijs.asn1.ASN1_block(); + in_window.org.pkijs.asn1.INTEGER.constructor = in_window.org.pkijs.asn1.INTEGER; + //************************************************************************************** + in_window.org.pkijs.asn1.INTEGER.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "INTEGER"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.INTEGER.prototype.isEqual = + function() + { + /// Compare two INTEGER object, or INTEGER and ArrayBuffer objects + /// + + if(arguments[0] instanceof in_window.org.pkijs.asn1.INTEGER) + { + if(this.value_block.is_hex_only && arguments[0].value_block.is_hex_only) // Compare two ArrayBuffers + return in_window.org.pkijs.isEqual_buffer(this.value_block.value_hex, arguments[0].value_block.value_hex); + else + { + if(this.value_block.is_hex_only === arguments[0].value_block.is_hex_only) + return (this.value_block.value_dec == arguments[0].value_block.value_dec); + else + return false; + } + } + else + { + if(arguments[0] instanceof ArrayBuffer) + return in_window.org.pkijs.isEqual_buffer(this.value_block.value_hex, arguments[0]); + else + return false; + } + + return false; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.INTEGER.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.INTEGER.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Declaration of ASN.1 ENUMERATED type class + //************************************************************************************** + in_window.org.pkijs.asn1.ENUMERATED = + function() + { + in_window.org.pkijs.asn1.INTEGER.call(this, arguments[0]); + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 10; // ENUMERATED + }; + //************************************************************************************** + in_window.org.pkijs.asn1.ENUMERATED.prototype = new in_window.org.pkijs.asn1.INTEGER(); + in_window.org.pkijs.asn1.ENUMERATED.constructor = in_window.org.pkijs.asn1.ENUMERATED; + //************************************************************************************** + in_window.org.pkijs.asn1.ENUMERATED.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "ENUMERATED"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.ENUMERATED.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = in_window.org.pkijs.asn1.INTEGER.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.ENUMERATED.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Declaration of ASN.1 OBJECT IDENTIFIER type class + //************************************************************************************** + local.SID_value_block = + function() + { + local.hex_block.call(this, arguments[0]); + + if(arguments[0] instanceof Object) + { + this.value_dec = in_window.org.pkijs.getValue(arguments[0], "value_dec", -1); + this.is_first_sid = in_window.org.pkijs.getValue(arguments[0], "is_first_sid", false); + } + else + { + this.value_dec = (-1); + this.is_first_sid = false; + } + }; + //************************************************************************************** + local.SID_value_block.prototype = new local.hex_block(); + local.SID_value_block.constructor = local.SID_value_block; + //************************************************************************************** + local.SID_value_block.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "sid_block"; + }; + //************************************************************************************** + local.SID_value_block.prototype.fromBER = + function(input_buffer, input_offset, input_length) + { + /// Base function for converting block from BER encoded array of bytes + /// ASN.1 BER encoded array + /// Offset in ASN.1 BER encoded array where decoding should be started + /// Maximum length of array of bytes which can be using in this function + + if(input_length == 0) + return input_offset; + + // #region Basic check for parameters + if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false) + return (-1); + // #endregion + + var int_buffer = new Uint8Array(input_buffer, input_offset, input_length); + + this.value_hex = new ArrayBuffer(input_length); + var view = new Uint8Array(this.value_hex); + + for(var i = 0; i < input_length; i++) + { + view[i] = int_buffer[i] & 0x7F; + + this.block_length++; + + if((int_buffer[i] & 0x80) == 0x00) + break; + } + + // #region Ajust size of value_hex buffer + var temp_value_hex = new ArrayBuffer(this.block_length); + var temp_view = new Uint8Array(temp_value_hex); + + for(var i = 0; i < this.block_length; i++) + temp_view[i] = view[i]; + + this.value_hex = util_copybuf(temp_value_hex); + view = new Uint8Array(this.value_hex); + // #endregion + + if((int_buffer[this.block_length - 1] & 0x80) != 0x00) + { + this.error = "End of input reached before message was fully decoded"; + return (-1); + } + + if(view[0] == 0x00) + this.warnings.push("Needlessly long format of SID encoding"); + + if(this.block_length <= 8) + this.value_dec = util_frombase(view, 7); + else + { + this.is_hex_only = true; + this.warnings.push("Too big SID for decoding, hex only"); + } + + return (input_offset + this.block_length); + }; + //************************************************************************************** + local.SID_value_block.prototype.toBER = + function(size_only) + { + /// Encoding of current ASN.1 block into ASN.1 encoded array (BER rules) + /// Flag that we need only a size of encoding, not a real array of bytes + + if(typeof size_only === "undefined") + size_only = false; + + if(this.is_hex_only) + { + if(size_only === true) + return (new ArrayBuffer(this.value_hex.byteLength)); + + var cur_view = new Uint8Array(this.value_hex); + + var ret_buf = new ArrayBuffer(this.block_length); + var ret_view = new Uint8Array(ret_buf); + + for(var i = 0; i < (this.block_length - 1) ; i++) + ret_view[i] = cur_view[i] | 0x80; + + ret_view[this.block_length - 1] = cur_view[this.block_length - 1]; + + return ret_buf; + } + else + { + var encoded_buf = util_tobase(this.value_dec, 7); + if(encoded_buf.byteLength === 0) + { + this.error = "Error during encoding SID value"; + return (new ArrayBuffer(0)); + } + + var ret_buf = new ArrayBuffer(encoded_buf.byteLength); + + if(size_only === false) + { + var encoded_view = new Uint8Array(encoded_buf); + var ret_view = new Uint8Array(ret_buf); + + for(var i = 0; i < (encoded_buf.byteLength - 1) ; i++) + ret_view[i] = encoded_view[i] | 0x80; + + ret_view[encoded_buf.byteLength - 1] = encoded_view[encoded_buf.byteLength - 1]; + } + + return ret_buf; + } + }; + //************************************************************************************** + local.SID_value_block.prototype.toString = + function() + { + var result = ""; + + if(this.is_hex_only === true) + result = to_hex_codes(this.value_hex); + else + { + if(this.is_first_sid) + { + var sid_value = this.value_dec; + + if(this.value_dec <= 39) + result = "0."; + else + { + if(this.value_dec <= 79) + { + result = "1."; + sid_value -= 40; + } + else + { + result = "2."; + sid_value -= 80; + } + } + + result = result + sid_value.toString(); + } + else + result = this.value_dec.toString(); + } + + return result; + }; + //************************************************************************************** + local.SID_value_block.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.hex_block.prototype.toJSON.call(this); + + _object.block_name = local.SID_value_block.prototype.block_name.call(this); + _object.value_dec = this.value_dec; + _object.is_first_sid = this.is_first_sid; + + return _object; + }; + //************************************************************************************** + local.OID_value_block = + function() + { + local.value_block.call(this, arguments[0]); + + this.value = new Array(); + + if(arguments[0] instanceof Object) + this.fromString(in_window.org.pkijs.getValue(arguments[0], "value", "")); + }; + //************************************************************************************** + local.OID_value_block.prototype = new local.value_block(); + local.OID_value_block.constructor = local.OID_value_block; + //************************************************************************************** + local.OID_value_block.prototype.fromBER = + function(input_buffer, input_offset, input_length) + { + /// Base function for converting block from BER encoded array of bytes + /// ASN.1 BER encoded array + /// Offset in ASN.1 BER encoded array where decoding should be started + /// Maximum length of array of bytes which can be using in this function + + var result_offset = input_offset; + + while(input_length > 0) + { + var sid_block = new local.SID_value_block(); + result_offset = sid_block.fromBER(input_buffer, result_offset, input_length); + if(result_offset == (-1)) + { + this.block_length = 0; + this.error = sid_block.error; + return result_offset; + } + + if(this.value.length == 0) + sid_block.is_first_sid = true; + + this.block_length += sid_block.block_length; + input_length -= sid_block.block_length; + + this.value.push(sid_block); + } + + return result_offset; + }; + //************************************************************************************** + local.OID_value_block.prototype.toBER = + function(size_only) + { + /// Encoding of current ASN.1 block into ASN.1 encoded array (BER rules) + /// Flag that we need only a size of encoding, not a real array of bytes + + if(typeof size_only === "undefined") + size_only = false; + + var ret_buf = new ArrayBuffer(0); + + for(var i = 0; i < this.value.length; i++) + { + var value_buf = this.value[i].toBER(size_only); + if(value_buf.byteLength === 0) + { + this.error = this.value[i].error; + return (new ArrayBuffer(0)); + } + + ret_buf = util_concatbuf(ret_buf, value_buf); + } + + return ret_buf; + }; + //************************************************************************************** + local.OID_value_block.prototype.fromString = + function(str) + { + this.value = new Array(); // Clear existing SID values + + var pos1 = 0; + var pos2 = 0; + + var sid = ""; + + var flag = false; + + do + { + pos2 = str.indexOf('.', pos1); + if(pos2 === (-1)) + sid = str.substr(pos1); + else + sid = str.substr(pos1, pos2 - pos1); + + pos1 = pos2 + 1; + + if(flag) + { + var sid_block = this.value[0]; + + var plus = 0; + + switch(sid_block.value_dec) + { + case 0: + break; + case 1: + plus = 40; + break; + case 2: + plus = 80; + break; + default: + this.value = new Array(); // clear SID array + return false; // ??? + } + + var parsedSID = parseInt(sid, 10); + if(isNaN(parsedSID)) + return true; + + sid_block.value_dec = parsedSID + plus; + + flag = false; + } + else + { + var sid_block = new local.SID_value_block(); + sid_block.value_dec = parseInt(sid, 10); + if(isNaN(sid_block.value_dec)) + return true; + + if(this.value.length === 0) + { + sid_block.is_first_sid = true; + flag = true; + } + + this.value.push(sid_block); + } + + } while(pos2 !== (-1)); + + return true; + }; + //************************************************************************************** + local.OID_value_block.prototype.toString = + function() + { + var result = ""; + var is_hex_only = false; + + for(var i = 0; i < this.value.length; i++) + { + is_hex_only = this.value[i].is_hex_only; + + var sid_str = this.value[i].toString(); + + if(i !== 0) + result = result + "."; + + if(is_hex_only) + { + sid_str = "{" + sid_str + "}"; + + if(this.value[i].is_first_sid) + result = "2.{" + sid_str + " - 80}"; + else + result = result + sid_str; + } + else + result = result + sid_str; + } + + return result; + }; + //************************************************************************************** + local.OID_value_block.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "OID_value_block"; + }; + //************************************************************************************** + local.OID_value_block.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.value_block.prototype.toJSON.call(this); + + _object.block_name = local.OID_value_block.prototype.block_name.call(this); + _object.value = local.OID_value_block.prototype.toString.call(this); + _object.sid_array = new Array(); + for(var i = 0; i < this.value.length; i++) + _object.sid_array.push(this.value[i].toJSON()); + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.OID = + function() + { + in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); + + this.value_block = new local.OID_value_block(arguments[0]); + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 6; // OBJECT IDENTIFIER + }; + //************************************************************************************** + in_window.org.pkijs.asn1.OID.prototype = new in_window.org.pkijs.asn1.ASN1_block(); + in_window.org.pkijs.asn1.OID.constructor = in_window.org.pkijs.asn1.OID; + //************************************************************************************** + in_window.org.pkijs.asn1.OID.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "OID"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.OID.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.OID.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Declaration of all string's classes + //************************************************************************************** + local.UTF8STRING_value_block = + function() + { + local.hex_block.call(this, arguments[0]); + + this.is_hex_only = true; + this.value = ""; // String representation of decoded ArrayBuffer + }; + //************************************************************************************** + local.UTF8STRING_value_block.prototype = new local.hex_block(); + local.UTF8STRING_value_block.constructor = local.UTF8STRING_value_block; + //************************************************************************************** + local.UTF8STRING_value_block.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "UTF8STRING_value_block"; + }; + //************************************************************************************** + local.UTF8STRING_value_block.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.hex_block.prototype.toJSON.call(this); + + _object.block_name = local.UTF8STRING_value_block.prototype.block_name.call(this); + _object.value = this.value; + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.UTF8STRING = + function() + { + in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); + + this.value_block = new local.UTF8STRING_value_block(); + + if(arguments[0] instanceof Object) + { + if("value" in arguments[0]) + in_window.org.pkijs.asn1.UTF8STRING.prototype.fromString.call(this,arguments[0].value); + } + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 12; // UTF8STRING + }; + //************************************************************************************** + in_window.org.pkijs.asn1.UTF8STRING.prototype = new in_window.org.pkijs.asn1.ASN1_block(); + in_window.org.pkijs.asn1.UTF8STRING.constructor = in_window.org.pkijs.asn1.UTF8STRING; + //************************************************************************************** + in_window.org.pkijs.asn1.UTF8STRING.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "UTF8STRING"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.UTF8STRING.prototype.fromBER = + function(input_buffer, input_offset, input_length) + { + /// Base function for converting block from BER encoded array of bytes + /// ASN.1 BER encoded array + /// Offset in ASN.1 BER encoded array where decoding should be started + /// Maximum length of array of bytes which can be using in this function + + var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length); + if(result_offset == (-1)) + { + this.error = this.value_block.error; + return result_offset; + } + + in_window.org.pkijs.asn1.UTF8STRING.prototype.fromBuffer.call(this, this.value_block.value_hex); + + if(this.id_block.error.length == 0) + this.block_length += this.id_block.block_length; + + if(this.len_block.error.length == 0) + this.block_length += this.len_block.block_length; + + if(this.value_block.error.length == 0) + this.block_length += this.value_block.block_length; + + return result_offset; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.UTF8STRING.prototype.fromBuffer = + function(input_buffer) + { + /// Array with encoded string + this.value_block.value = String.fromCharCode.apply(null, new Uint8Array(input_buffer)); + + try + { + this.value_block.value = decodeURIComponent(escape(this.value_block.value)); + } + catch(ex) + { + this.warnings.push("Error during \"decodeURIComponent\": " + ex + ", using raw string"); + } + }; + //************************************************************************************** + in_window.org.pkijs.asn1.UTF8STRING.prototype.fromString = + function(input_string) + { + /// String with UNIVERSALSTRING value + + var str = unescape(encodeURIComponent(input_string)); + var str_len = str.length; + + this.value_block.value_hex = new ArrayBuffer(str_len); + var view = new Uint8Array(this.value_block.value_hex); + + for(var i = 0; i < str_len; i++) + view[i] = str.charCodeAt(i); + + this.value_block.value = input_string; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.UTF8STRING.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.UTF8STRING.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + local.BMPSTRING_value_block = + function() + { + local.hex_block.call(this, arguments[0]); + + this.is_hex_only = true; + this.value = ""; + }; + //************************************************************************************** + local.BMPSTRING_value_block.prototype = new local.hex_block(); + local.BMPSTRING_value_block.constructor = local.BMPSTRING_value_block; + //************************************************************************************** + local.BMPSTRING_value_block.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "BMPSTRING_value_block"; + }; + //************************************************************************************** + local.BMPSTRING_value_block.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.hex_block.prototype.toJSON.call(this); + + _object.block_name = local.BMPSTRING_value_block.prototype.block_name.call(this); + _object.value = this.value; + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.BMPSTRING = + function() + { + in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); + + this.value_block = new local.BMPSTRING_value_block(); + + if(arguments[0] instanceof Object) + { + if("value" in arguments[0]) + in_window.org.pkijs.asn1.BMPSTRING.prototype.fromString.call(this, arguments[0].value); + } + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 30; // BMPSTRING + }; + //************************************************************************************** + in_window.org.pkijs.asn1.BMPSTRING.prototype = new in_window.org.pkijs.asn1.ASN1_block(); + in_window.org.pkijs.asn1.BMPSTRING.constructor = in_window.org.pkijs.asn1.BMPSTRING; + //************************************************************************************** + in_window.org.pkijs.asn1.BMPSTRING.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "BMPSTRING"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.BMPSTRING.prototype.fromBER = + function(input_buffer, input_offset, input_length) + { + /// Base function for converting block from BER encoded array of bytes + /// ASN.1 BER encoded array + /// Offset in ASN.1 BER encoded array where decoding should be started + /// Maximum length of array of bytes which can be using in this function + + var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length); + if(result_offset == (-1)) + { + this.error = this.value_block.error; + return result_offset; + } + + in_window.org.pkijs.asn1.BMPSTRING.prototype.fromBuffer.call(this, this.value_block.value_hex); + + if(this.id_block.error.length == 0) + this.block_length += this.id_block.block_length; + + if(this.len_block.error.length == 0) + this.block_length += this.len_block.block_length; + + if(this.value_block.error.length == 0) + this.block_length += this.value_block.block_length; + + return result_offset; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.BMPSTRING.prototype.fromBuffer = + function(input_buffer) + { + /// Array with encoded string + + var copy_buffer = in_window.org.pkijs.copyBuffer(input_buffer); + + var value_view = new Uint8Array(copy_buffer); + + for(var i = 0; i < value_view.length; i = i + 2) + { + var temp = value_view[i]; + + value_view[i] = value_view[i + 1]; + value_view[i + 1] = temp; + } + + this.value_block.value = String.fromCharCode.apply(null, new Uint16Array(copy_buffer)); + }; + //************************************************************************************** + in_window.org.pkijs.asn1.BMPSTRING.prototype.fromString = + function(input_string) + { + /// String with UNIVERSALSTRING value + + var str_length = input_string.length; + + this.value_block.value_hex = new ArrayBuffer(str_length * 2); + var value_hex_view = new Uint8Array(this.value_block.value_hex); + + for(var i = 0; i < str_length; i++) + { + var code_buf = util_tobase(input_string.charCodeAt(i), 8); + var code_view = new Uint8Array(code_buf); + if(code_view.length > 2) + continue; + + var dif = 2 - code_view.length; + + for(var j = (code_view.length - 1) ; j >= 0; j--) + value_hex_view[i * 2 + j + dif] = code_view[j]; + } + + this.value_block.value = input_string; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.BMPSTRING.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.BMPSTRING.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + local.UNIVERSALSTRING_value_block = + function() + { + local.hex_block.call(this, arguments[0]); + + this.is_hex_only = true; + this.value = ""; + }; + //************************************************************************************** + local.UNIVERSALSTRING_value_block.prototype = new local.hex_block(); + local.UNIVERSALSTRING_value_block.constructor = local.UNIVERSALSTRING_value_block; + //************************************************************************************** + local.UNIVERSALSTRING_value_block.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "UNIVERSALSTRING_value_block"; + }; + //************************************************************************************** + local.UNIVERSALSTRING_value_block.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.hex_block.prototype.toJSON.call(this); + + _object.block_name = local.UNIVERSALSTRING_value_block.prototype.block_name.call(this); + _object.value = this.value; + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.UNIVERSALSTRING = + function() + { + in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); + + this.value_block = new local.UNIVERSALSTRING_value_block(); + + if(arguments[0] instanceof Object) + { + if("value" in arguments[0]) + in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.fromString.call(this, arguments[0].value); + } + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 28; // UNIVERSALSTRING + }; + //************************************************************************************** + in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype = new in_window.org.pkijs.asn1.ASN1_block(); + in_window.org.pkijs.asn1.UNIVERSALSTRING.constructor = in_window.org.pkijs.asn1.UNIVERSALSTRING; + //************************************************************************************** + in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "UNIVERSALSTRING"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.fromBER = + function(input_buffer, input_offset, input_length) + { + /// Base function for converting block from BER encoded array of bytes + /// ASN.1 BER encoded array + /// Offset in ASN.1 BER encoded array where decoding should be started + /// Maximum length of array of bytes which can be using in this function + + var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length); + if(result_offset == (-1)) + { + this.error = this.value_block.error; + return result_offset; + } + + in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.fromBuffer.call(this, this.value_block.value_hex); + + if(this.id_block.error.length == 0) + this.block_length += this.id_block.block_length; + + if(this.len_block.error.length == 0) + this.block_length += this.len_block.block_length; + + if(this.value_block.error.length == 0) + this.block_length += this.value_block.block_length; + + return result_offset; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.fromBuffer = + function(input_buffer) + { + /// Array with encoded string + + var copy_buffer = in_window.org.pkijs.copyBuffer(input_buffer); + + var value_view = new Uint8Array(copy_buffer); + + for(var i = 0; i < value_view.length; i = i + 4) + { + value_view[i] = value_view[i + 3]; + value_view[i + 1] = value_view[i + 2]; + value_view[i + 2] = 0x00; + value_view[i + 3] = 0x00; + } + + this.value_block.value = String.fromCharCode.apply(null, new Uint32Array(copy_buffer)); + }; + //************************************************************************************** + in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.fromString = + function(input_string) + { + /// String with UNIVERSALSTRING value + + var str_length = input_string.length; + + this.value_block.value_hex = new ArrayBuffer(str_length * 4); + var value_hex_view = new Uint8Array(this.value_block.value_hex); + + for(var i = 0; i < str_length; i++) + { + var code_buf = util_tobase(input_string.charCodeAt(i), 8); + var code_view = new Uint8Array(code_buf); + if(code_view.length > 4) + continue; + + var dif = 4 - code_view.length; + + for(var j = (code_view.length - 1) ; j >= 0; j--) + value_hex_view[i*4 + j + dif] = code_view[j]; + } + + this.value_block.value = input_string; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + local.SIMPLESTRING_value_block = + function() + { + local.hex_block.call(this, arguments[0]); + + /// Native string representation + this.value = ""; + this.is_hex_only = true; + }; + //************************************************************************************** + local.SIMPLESTRING_value_block.prototype = new local.hex_block(); + local.SIMPLESTRING_value_block.constructor = local.SIMPLESTRING_value_block; + //************************************************************************************** + local.SIMPLESTRING_value_block.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "SIMPLESTRING_value_block"; + }; + //************************************************************************************** + local.SIMPLESTRING_value_block.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.hex_block.prototype.toJSON.call(this); + + _object.block_name = local.SIMPLESTRING_value_block.prototype.block_name.call(this); + _object.value = this.value; + + return _object; + }; + //************************************************************************************** + local.SIMPLESTRING_block = + function() + { + in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]); + + this.value_block = new local.SIMPLESTRING_value_block(); + + if(arguments[0] instanceof Object) + { + if("value" in arguments[0]) + local.SIMPLESTRING_block.prototype.fromString.call(this, arguments[0].value); + } + }; + //************************************************************************************** + local.SIMPLESTRING_block.prototype = new in_window.org.pkijs.asn1.ASN1_block(); + local.SIMPLESTRING_block.constructor = local.SIMPLESTRING_block; + //************************************************************************************** + local.SIMPLESTRING_block.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "SIMPLESTRING"; + }; + //************************************************************************************** + local.SIMPLESTRING_block.prototype.fromBER = + function(input_buffer, input_offset, input_length) + { + /// Base function for converting block from BER encoded array of bytes + /// ASN.1 BER encoded array + /// Offset in ASN.1 BER encoded array where decoding should be started + /// Maximum length of array of bytes which can be using in this function + + var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length); + if(result_offset == (-1)) + { + this.error = this.value_block.error; + return result_offset; + } + + local.SIMPLESTRING_block.prototype.fromBuffer.call(this, this.value_block.value_hex); + + if(this.id_block.error.length == 0) + this.block_length += this.id_block.block_length; + + if(this.len_block.error.length == 0) + this.block_length += this.len_block.block_length; + + if(this.value_block.error.length == 0) + this.block_length += this.value_block.block_length; + + return result_offset; + }; + //************************************************************************************** + local.SIMPLESTRING_block.prototype.fromBuffer = + function(input_buffer) + { + /// Array with encoded string + + this.value_block.value = String.fromCharCode.apply(null, new Uint8Array(input_buffer)); + }; + //************************************************************************************** + local.SIMPLESTRING_block.prototype.fromString = + function(input_string) + { + /// String with UNIVERSALSTRING value + var str_len = input_string.length; + + this.value_block.value_hex = new ArrayBuffer(str_len); + var view = new Uint8Array(this.value_block.value_hex); + + for(var i = 0; i < str_len; i++) + view[i] = input_string.charCodeAt(i); + + this.value_block.value = input_string; + }; + //************************************************************************************** + local.SIMPLESTRING_block.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this); + + _object.block_name = local.SIMPLESTRING_block.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.NUMERICSTRING = + function() + { + local.SIMPLESTRING_block.call(this, arguments[0]); + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 18; // NUMERICSTRING + }; + //************************************************************************************** + in_window.org.pkijs.asn1.NUMERICSTRING.prototype = new local.SIMPLESTRING_block(); + in_window.org.pkijs.asn1.NUMERICSTRING.constructor = in_window.org.pkijs.asn1.NUMERICSTRING; + //************************************************************************************** + in_window.org.pkijs.asn1.NUMERICSTRING.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "NUMERICSTRING"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.NUMERICSTRING.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.NUMERICSTRING.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.PRINTABLESTRING = + function() + { + local.SIMPLESTRING_block.call(this, arguments[0]); + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 19; // PRINTABLESTRING + }; + //************************************************************************************** + in_window.org.pkijs.asn1.PRINTABLESTRING.prototype = new local.SIMPLESTRING_block(); + in_window.org.pkijs.asn1.PRINTABLESTRING.constructor = in_window.org.pkijs.asn1.PRINTABLESTRING; + //************************************************************************************** + in_window.org.pkijs.asn1.PRINTABLESTRING.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "PRINTABLESTRING"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.PRINTABLESTRING.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.PRINTABLESTRING.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.TELETEXSTRING = + function() + { + local.SIMPLESTRING_block.call(this, arguments[0]); + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 20; // TELETEXSTRING + }; + //************************************************************************************** + in_window.org.pkijs.asn1.TELETEXSTRING.prototype = new local.SIMPLESTRING_block(); + in_window.org.pkijs.asn1.TELETEXSTRING.constructor = in_window.org.pkijs.asn1.TELETEXSTRING; + //************************************************************************************** + in_window.org.pkijs.asn1.TELETEXSTRING.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "TELETEXSTRING"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.TELETEXSTRING.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.TELETEXSTRING.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.VIDEOTEXSTRING = + function() + { + local.SIMPLESTRING_block.call(this, arguments[0]); + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 21; // VIDEOTEXSTRING + }; + //************************************************************************************** + in_window.org.pkijs.asn1.VIDEOTEXSTRING.prototype = new local.SIMPLESTRING_block(); + in_window.org.pkijs.asn1.VIDEOTEXSTRING.constructor = in_window.org.pkijs.asn1.VIDEOTEXSTRING; + //************************************************************************************** + in_window.org.pkijs.asn1.VIDEOTEXSTRING.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "VIDEOTEXSTRING"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.VIDEOTEXSTRING.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.VIDEOTEXSTRING.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.IA5STRING = + function() + { + local.SIMPLESTRING_block.call(this, arguments[0]); + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 22; // IA5STRING + }; + //************************************************************************************** + in_window.org.pkijs.asn1.IA5STRING.prototype = new local.SIMPLESTRING_block(); + in_window.org.pkijs.asn1.IA5STRING.constructor = in_window.org.pkijs.asn1.IA5STRING; + //************************************************************************************** + in_window.org.pkijs.asn1.IA5STRING.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "IA5STRING"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.IA5STRING.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.IA5STRING.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.GRAPHICSTRING = + function() + { + local.SIMPLESTRING_block.call(this, arguments[0]); + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 25; // GRAPHICSTRING + }; + //************************************************************************************** + in_window.org.pkijs.asn1.GRAPHICSTRING.prototype = new local.SIMPLESTRING_block(); + in_window.org.pkijs.asn1.GRAPHICSTRING.constructor = in_window.org.pkijs.asn1.GRAPHICSTRING; + //************************************************************************************** + in_window.org.pkijs.asn1.GRAPHICSTRING.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "GRAPHICSTRING"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.GRAPHICSTRING.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.GRAPHICSTRING.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.VISIBLESTRING = + function() + { + local.SIMPLESTRING_block.call(this, arguments[0]); + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 26; // VISIBLESTRING + }; + //************************************************************************************** + in_window.org.pkijs.asn1.VISIBLESTRING.prototype = new local.SIMPLESTRING_block(); + in_window.org.pkijs.asn1.VISIBLESTRING.constructor = in_window.org.pkijs.asn1.VISIBLESTRING; + //************************************************************************************** + in_window.org.pkijs.asn1.VISIBLESTRING.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "VISIBLESTRING"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.VISIBLESTRING.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.VISIBLESTRING.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.GENERALSTRING = + function() + { + local.SIMPLESTRING_block.call(this, arguments[0]); + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 27; // GENERALSTRING + }; + //************************************************************************************** + in_window.org.pkijs.asn1.GENERALSTRING.prototype = new local.SIMPLESTRING_block(); + in_window.org.pkijs.asn1.GENERALSTRING.constructor = in_window.org.pkijs.asn1.GENERALSTRING; + //************************************************************************************** + in_window.org.pkijs.asn1.GENERALSTRING.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "GENERALSTRING"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.GENERALSTRING.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.GENERALSTRING.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.CHARACTERSTRING = + function() + { + local.SIMPLESTRING_block.call(this, arguments[0]); + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 29; // CHARACTERSTRING + }; + //************************************************************************************** + in_window.org.pkijs.asn1.CHARACTERSTRING.prototype = new local.SIMPLESTRING_block(); + in_window.org.pkijs.asn1.CHARACTERSTRING.constructor = in_window.org.pkijs.asn1.CHARACTERSTRING; + //************************************************************************************** + in_window.org.pkijs.asn1.CHARACTERSTRING.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "CHARACTERSTRING"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.CHARACTERSTRING.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.CHARACTERSTRING.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Declaration of all date and time classes + //************************************************************************************** + in_window.org.pkijs.asn1.UTCTIME = + function() + { + in_window.org.pkijs.asn1.VISIBLESTRING.call(this, arguments[0]); + + this.year = 0; + this.month = 0; + this.day = 0; + this.hour = 0; + this.minute = 0; + this.second = 0; + + // #region Create UTCTIME from ASN.1 UTC string value + if((arguments[0] instanceof Object) && ("value" in arguments[0])) + { + in_window.org.pkijs.asn1.UTCTIME.prototype.fromString.call(this, arguments[0].value); + + this.value_block.value_hex = new ArrayBuffer(arguments[0].value.length); + var view = new Uint8Array(this.value_block.value_hex); + + for(var i = 0; i < arguments[0].value.length; i++) + view[i] = arguments[0].value.charCodeAt(i); + } + // #endregion + // #region Create UTCTIME from JavaScript Date type + if((arguments[0] instanceof Object) && ("value_date" in arguments[0])) + { + in_window.org.pkijs.asn1.UTCTIME.prototype.fromDate.call(this, arguments[0].value_date); + this.value_block.value_hex = in_window.org.pkijs.asn1.UTCTIME.prototype.toBuffer.call(this); + } + // #endregion + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 23; // UTCTIME + }; + //************************************************************************************** + in_window.org.pkijs.asn1.UTCTIME.prototype = new in_window.org.pkijs.asn1.VISIBLESTRING(); + in_window.org.pkijs.asn1.UTCTIME.constructor = in_window.org.pkijs.asn1.UTCTIME; + //************************************************************************************** + in_window.org.pkijs.asn1.UTCTIME.prototype.fromBER = + function(input_buffer, input_offset, input_length) + { + /// Base function for converting block from BER encoded array of bytes + /// ASN.1 BER encoded array + /// Offset in ASN.1 BER encoded array where decoding should be started + /// Maximum length of array of bytes which can be using in this function + + var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length); + if(result_offset == (-1)) + { + this.error = this.value_block.error; + return result_offset; + } + + in_window.org.pkijs.asn1.UTCTIME.prototype.fromBuffer.call(this, this.value_block.value_hex); + + if(this.id_block.error.length == 0) + this.block_length += this.id_block.block_length; + + if(this.len_block.error.length == 0) + this.block_length += this.len_block.block_length; + + if(this.value_block.error.length == 0) + this.block_length += this.value_block.block_length; + + return result_offset; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.UTCTIME.prototype.fromBuffer = + function(input_buffer) + { + in_window.org.pkijs.asn1.UTCTIME.prototype.fromString.call(this, String.fromCharCode.apply(null, new Uint8Array(input_buffer))); + }; + //************************************************************************************** + in_window.org.pkijs.asn1.UTCTIME.prototype.toBuffer = + function() + { + var str = in_window.org.pkijs.asn1.UTCTIME.prototype.toString.call(this); + + var buffer = new ArrayBuffer(str.length); + var view = new Uint8Array(buffer); + + for(var i = 0; i < str.length; i++) + view[i] = str.charCodeAt(i); + + return buffer; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.UTCTIME.prototype.fromDate = + function(input_date) + { + /// Create "UTCTime" ASN.1 type from JavaScript "Date" type + + this.year = input_date.getUTCFullYear(); + this.month = input_date.getUTCMonth() + 1; + this.day = input_date.getUTCDate(); + this.hour = input_date.getUTCHours(); + this.minute = input_date.getUTCMinutes(); + this.second = input_date.getUTCSeconds(); + }; + //************************************************************************************** + in_window.org.pkijs.asn1.UTCTIME.prototype.toDate = + function() + { + return (new Date(Date.UTC(this.year, this.month - 1, this.day, this.hour, this.minute, this.second))); + }; + //************************************************************************************** + in_window.org.pkijs.asn1.UTCTIME.prototype.fromString = + function(input_string) + { + /// Create "UTCTime" ASN.1 type from JavaScript "String" type + + // #region Parse input string + var parser = /(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})Z/ig; + var parser_array = parser.exec(input_string); + if(parser_array === null) + { + this.error = "Wrong input string for convertion"; + return; + } + // #endregion + + // #region Store parsed values + var year = parseInt(parser_array[1], 10); + if(year >= 50) + this.year = 1900 + year; + else + this.year = 2000 + year; + + this.month = parseInt(parser_array[2], 10); + this.day = parseInt(parser_array[3], 10); + this.hour = parseInt(parser_array[4], 10); + this.minute = parseInt(parser_array[5], 10); + this.second = parseInt(parser_array[6], 10); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.asn1.UTCTIME.prototype.toString = + function() + { + var output_array = new Array(7); + + output_array[0] = in_window.org.pkijs.padNumber(((this.year < 2000) ? (this.year - 1900) : (this.year - 2000)), 2); + output_array[1] = in_window.org.pkijs.padNumber(this.month, 2); + output_array[2] = in_window.org.pkijs.padNumber(this.day, 2); + output_array[3] = in_window.org.pkijs.padNumber(this.hour, 2); + output_array[4] = in_window.org.pkijs.padNumber(this.minute, 2); + output_array[5] = in_window.org.pkijs.padNumber(this.second, 2); + output_array[6] = "Z"; + + return output_array.join(''); + }; + //************************************************************************************** + in_window.org.pkijs.asn1.UTCTIME.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "UTCTIME"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.UTCTIME.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = in_window.org.pkijs.asn1.VISIBLESTRING.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.UTCTIME.prototype.block_name.call(this); + _object.year = this.year; + _object.month = this.month; + _object.day = this.day; + _object.hour = this.hour; + _object.minute = this.minute; + _object.second = this.second; + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.GENERALIZEDTIME = + function() + { + in_window.org.pkijs.asn1.VISIBLESTRING.call(this, arguments[0]); + + this.year = 0; + this.month = 0; + this.day = 0; + this.hour = 0; + this.minute = 0; + this.second = 0; + this.millisecond = 0; + + // #region Create GeneralizedTime from ASN.1 string value + if((arguments[0] instanceof Object) && ("value" in arguments[0])) + { + in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromString.call(this, arguments[0].value); + + this.value_block.value_hex = new ArrayBuffer(arguments[0].value.length); + var view = new Uint8Array(this.value_block.value_hex); + + for(var i = 0; i < arguments[0].value.length; i++) + view[i] = arguments[0].value.charCodeAt(i); + } + // #endregion + // #region Create GeneralizedTime from JavaScript Date type + if((arguments[0] instanceof Object) && ("value_date" in arguments[0])) + { + in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromDate.call(this, arguments[0].value_date); + this.value_block.value_hex = in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.toBuffer.call(this); + } + // #endregion + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 24; // GENERALIZEDTIME + }; + //************************************************************************************** + in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype = new in_window.org.pkijs.asn1.VISIBLESTRING(); + in_window.org.pkijs.asn1.GENERALIZEDTIME.constructor = in_window.org.pkijs.asn1.GENERALIZEDTIME; + //************************************************************************************** + in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromBER = + function(input_buffer, input_offset, input_length) + { + /// Base function for converting block from BER encoded array of bytes + /// ASN.1 BER encoded array + /// Offset in ASN.1 BER encoded array where decoding should be started + /// Maximum length of array of bytes which can be using in this function + + var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length); + if(result_offset == (-1)) + { + this.error = this.value_block.error; + return result_offset; + } + + in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromBuffer.call(this, this.value_block.value_hex); + + if(this.id_block.error.length == 0) + this.block_length += this.id_block.block_length; + + if(this.len_block.error.length == 0) + this.block_length += this.len_block.block_length; + + if(this.value_block.error.length == 0) + this.block_length += this.value_block.block_length; + + return result_offset; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromBuffer = + function(input_buffer) + { + in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromString.call(this, String.fromCharCode.apply(null, new Uint8Array(input_buffer))); + }; + //************************************************************************************** + in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.toBuffer = + function() + { + var str = in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.toString.call(this); + + var buffer = new ArrayBuffer(str.length); + var view = new Uint8Array(buffer); + + for(var i = 0; i < str.length; i++) + view[i] = str.charCodeAt(i); + + return buffer; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromDate = + function(input_date) + { + /// Create "GeneralizedTime" ASN.1 type from JavaScript "Date" type + + this.year = input_date.getUTCFullYear(); + this.month = input_date.getUTCMonth() + 1; + this.day = input_date.getUTCDate(); + this.hour = input_date.getUTCHours(); + this.minute = input_date.getUTCMinutes(); + this.second = input_date.getUTCSeconds(); + this.millisecond = input_date.getUTCMilliseconds(); + }; + //************************************************************************************** + in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.toDate = + function() + { + return (new Date(Date.UTC(this.year, this.month - 1, this.day, this.hour, this.minute, this.second, this.millisecond))); + }; + //************************************************************************************** + in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromString = + function(input_string) + { + /// Create "GeneralizedTime" ASN.1 type from JavaScript "String" type + + // #region Initial variables + var isUTC = false; + + var timeString = ""; + var dateTimeString = ""; + var fractionPart = 0; + + var parser; + + var hourDifference = 0; + var minuteDifference = 0; + // #endregion + + // #region Convert as UTC time + if(input_string[input_string.length - 1] == "Z") + { + timeString = input_string.substr(0, input_string.length - 1); + + isUTC = true; + } + // #endregion + // #region Convert as local time + else + { + var number = new Number(input_string[input_string.length - 1]); + + if(isNaN(number.valueOf())) + throw new Error("Wrong input string for convertion"); + + timeString = input_string; + } + // #endregion + + // #region Check that we do not have a "+" and "-" symbols inside UTC time + if(isUTC) + { + if(timeString.indexOf("+") != (-1)) + throw new Error("Wrong input string for convertion"); + + if(timeString.indexOf("-") != (-1)) + throw new Error("Wrong input string for convertion"); + } + // #endregion + // #region Get "UTC time difference" in case of local time + else + { + var multiplier = 1; + var differencePosition = timeString.indexOf("+"); + var differenceString = ""; + + if(differencePosition == (-1)) + { + differencePosition = timeString.indexOf("-"); + multiplier = (-1); + } + + if(differencePosition != (-1)) + { + differenceString = timeString.substr(differencePosition + 1); + timeString = timeString.substr(0, differencePosition); + + if((differenceString.length != 2) && (differenceString.length != 4)) + throw new Error("Wrong input string for convertion"); + + var number = new Number(differenceString.substr(0, 2)); + + if(isNaN(number.valueOf())) + throw new Error("Wrong input string for convertion"); + + hourDifference = multiplier * number; + + if(differenceString.length == 4) + { + number = new Number(differenceString.substr(2, 2)); + + if(isNaN(number.valueOf())) + throw new Error("Wrong input string for convertion"); + + minuteDifference = multiplier * number; + } + } + } + // #endregion + + // #region Get position of fraction point + var fractionPointPosition = timeString.indexOf("."); // Check for "full stop" symbol + if(fractionPointPosition == (-1)) + fractionPointPosition = timeString.indexOf(","); // Check for "comma" symbol + // #endregion + + // #region Get fraction part + if(fractionPointPosition != (-1)) + { + var fractionPartCheck = new Number("0" + timeString.substr(fractionPointPosition)); + + if(isNaN(fractionPartCheck.valueOf())) + throw new Error("Wrong input string for convertion"); + + fractionPart = fractionPartCheck.valueOf(); + + dateTimeString = timeString.substr(0, fractionPointPosition); + } + else + dateTimeString = timeString; + // #endregion + + // #region Parse internal date + switch(true) + { + case (dateTimeString.length == 8): // "YYYYMMDD" + parser = /(\d{4})(\d{2})(\d{2})/ig; + if(fractionPointPosition !== (-1)) + throw new Error("Wrong input string for convertion"); // Here we should not have a "fraction point" + break; + case (dateTimeString.length == 10): // "YYYYMMDDHH" + parser = /(\d{4})(\d{2})(\d{2})(\d{2})/ig; + + if(fractionPointPosition !== (-1)) + { + var fractionResult = 60 * fractionPart; + this.minute = Math.floor(fractionResult); + + fractionResult = 60 * (fractionResult - this.minute); + this.second = Math.floor(fractionResult); + + fractionResult = 1000 * (fractionResult - this.second); + this.millisecond = Math.floor(fractionResult); + } + break; + case (dateTimeString.length == 12): // "YYYYMMDDHHMM" + parser = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})/ig; + + if(fractionPointPosition !== (-1)) + { + var fractionResult = 60 * fractionPart; + this.second = Math.floor(fractionResult); + + fractionResult = 1000 * (fractionResult - this.second); + this.millisecond = Math.floor(fractionResult); + } + break; + case (dateTimeString.length == 14): // "YYYYMMDDHHMMSS" + parser = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/ig; + + if(fractionPointPosition !== (-1)) + { + var fractionResult = 1000 * fractionPart; + this.millisecond = Math.floor(fractionResult); + } + break; + default: + throw new Error("Wrong input string for convertion"); + } + // #endregion + + // #region Put parsed values at right places + var parser_array = parser.exec(dateTimeString); + if(parser_array == null) + throw new Error("Wrong input string for convertion"); + + for(var j = 1; j < parser_array.length; j++) + { + switch(j) + { + case 1: + this.year = parseInt(parser_array[j], 10); + break; + case 2: + this.month = parseInt(parser_array[j], 10); + break; + case 3: + this.day = parseInt(parser_array[j], 10); + break; + case 4: + this.hour = parseInt(parser_array[j], 10) + hourDifference; + break; + case 5: + this.minute = parseInt(parser_array[j], 10) + minuteDifference; + break; + case 6: + this.second = parseInt(parser_array[j], 10); + break; + default: + throw new Error("Wrong input string for convertion"); + } + } + // #endregion + + // #region Get final date + if(isUTC == false) + { + var tempDate = new Date(this.year, this.month, this.day, this.hour, this.minute, this.second, this.millisecond); + + this.year = tempDate.getUTCFullYear(); + this.month = tempDate.getUTCMonth(); + this.day = tempDate.getUTCDay(); + this.hour = tempDate.getUTCHours(); + this.minute = tempDate.getUTCMinutes(); + this.second = tempDate.getUTCSeconds(); + this.millisecond = tempDate.getUTCMilliseconds(); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.toString = + function() + { + var output_array = new Array(); + + output_array.push(in_window.org.pkijs.padNumber(this.year, 4)); + output_array.push(in_window.org.pkijs.padNumber(this.month, 2)); + output_array.push(in_window.org.pkijs.padNumber(this.day, 2)); + output_array.push(in_window.org.pkijs.padNumber(this.hour, 2)); + output_array.push(in_window.org.pkijs.padNumber(this.minute, 2)); + output_array.push(in_window.org.pkijs.padNumber(this.second, 2)); + if(this.millisecond != 0) + { + output_array.push("."); + output_array.push(in_window.org.pkijs.padNumber(this.millisecond, 3)); + } + output_array.push("Z"); + + return output_array.join(''); + }; + //************************************************************************************** + in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "GENERALIZEDTIME"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = in_window.org.pkijs.asn1.VISIBLESTRING.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.block_name.call(this); + _object.year = this.year; + _object.month = this.month; + _object.day = this.day; + _object.hour = this.hour; + _object.minute = this.minute; + _object.second = this.second; + _object.millisecond = this.millisecond; + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.DATE = + function() + { + in_window.org.pkijs.asn1.UTF8STRING.call(this, arguments[0]); + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 31; // DATE + }; + //************************************************************************************** + in_window.org.pkijs.asn1.DATE.prototype = new in_window.org.pkijs.asn1.UTF8STRING(); + in_window.org.pkijs.asn1.DATE.constructor = in_window.org.pkijs.asn1.DATE; + //************************************************************************************** + in_window.org.pkijs.asn1.DATE.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "DATE"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.DATE.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = in_window.org.pkijs.asn1.UTF8STRING.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.DATE.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.TIMEOFDAY = + function() + { + in_window.org.pkijs.asn1.UTF8STRING.call(this, arguments[0]); + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 32; // TIMEOFDAY + }; + //************************************************************************************** + in_window.org.pkijs.asn1.TIMEOFDAY.prototype = new in_window.org.pkijs.asn1.UTF8STRING(); + in_window.org.pkijs.asn1.TIMEOFDAY.constructor = in_window.org.pkijs.asn1.TIMEOFDAY; + //************************************************************************************** + in_window.org.pkijs.asn1.TIMEOFDAY.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "TIMEOFDAY"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.TIMEOFDAY.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = in_window.org.pkijs.asn1.UTF8STRING.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.TIMEOFDAY.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.DATETIME = + function() + { + in_window.org.pkijs.asn1.UTF8STRING.call(this, arguments[0]); + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 33; // DATETIME + }; + //************************************************************************************** + in_window.org.pkijs.asn1.DATETIME.prototype = new in_window.org.pkijs.asn1.UTF8STRING(); + in_window.org.pkijs.asn1.DATETIME.constructor = in_window.org.pkijs.asn1.DATETIME; + //************************************************************************************** + in_window.org.pkijs.asn1.DATETIME.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "DATETIME"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.DATETIME.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = in_window.org.pkijs.asn1.UTF8STRING.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.DATETIME.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.DURATION = + function() + { + in_window.org.pkijs.asn1.UTF8STRING.call(this, arguments[0]); + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 34; // DURATION + }; + //************************************************************************************** + in_window.org.pkijs.asn1.DURATION.prototype = new in_window.org.pkijs.asn1.UTF8STRING(); + in_window.org.pkijs.asn1.DURATION.constructor = in_window.org.pkijs.asn1.DURATION; + //************************************************************************************** + in_window.org.pkijs.asn1.DURATION.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "DURATION"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.DURATION.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = in_window.org.pkijs.asn1.UTF8STRING.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.DURATION.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.TIME = + function() + { + in_window.org.pkijs.asn1.UTF8STRING.call(this, arguments[0]); + + this.id_block.tag_class = 1; // UNIVERSAL + this.id_block.tag_number = 14; // TIME + }; + //************************************************************************************** + in_window.org.pkijs.asn1.TIME.prototype = new in_window.org.pkijs.asn1.UTF8STRING(); + in_window.org.pkijs.asn1.TIME.constructor = in_window.org.pkijs.asn1.TIME; + //************************************************************************************** + in_window.org.pkijs.asn1.TIME.prototype.block_name = + function() + { + /// Aux function, need to get a block name. Need to have it here for inhiritence + + return "TIME"; + }; + //************************************************************************************** + in_window.org.pkijs.asn1.TIME.prototype.toJSON = + function() + { + /// Convertion for the block to JSON object + + var _object = in_window.org.pkijs.asn1.UTF8STRING.prototype.toJSON.call(this); + + _object.block_name = in_window.org.pkijs.asn1.TIME.prototype.block_name.call(this); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Declaration of special ASN.1 schema type CHOICE + //************************************************************************************** + in_window.org.pkijs.asn1.CHOICE = + function() + { + if(arguments[0] instanceof Object) + { + this.value = in_window.org.pkijs.getValue(arguments[0], "value", new Array()); // Array of ASN.1 types for make a choice from + this.optional = in_window.org.pkijs.getValue(arguments[0], "optional", false); + } + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Declaration of special ASN.1 schema type ANY + //************************************************************************************** + in_window.org.pkijs.asn1.ANY = + function() + { + if(arguments[0] instanceof Object) + { + this.name = in_window.org.pkijs.getValue(arguments[0], "name", ""); + this.optional = in_window.org.pkijs.getValue(arguments[0], "optional", false); + } + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Declaration of special ASN.1 schema type REPEATED + //************************************************************************************** + in_window.org.pkijs.asn1.REPEATED = + function() + { + if(arguments[0] instanceof Object) + { + this.name = in_window.org.pkijs.getValue(arguments[0], "name", ""); + this.optional = in_window.org.pkijs.getValue(arguments[0], "optional", false); + this.value = in_window.org.pkijs.getValue(arguments[0], "value", new in_window.org.pkijs.asn1.ANY()); + this.local = in_window.org.pkijs.getValue(arguments[0], "local", false); // Could local or global array to store elements + } + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Major ASN.1 BER decoding function + //************************************************************************************** + function fromBER_raw(input_buffer, input_offset, input_length) + { + var incoming_offset = input_offset; // Need to store initial offset since "input_offset" is changing in the function + + // #region Local function changing a type for ASN.1 classes + function local_change_type(input_object, new_type) + { + if(input_object instanceof new_type) + return input_object; + + var new_object = new new_type(); + new_object.id_block = input_object.id_block; + new_object.len_block = input_object.len_block; + new_object.warnings = input_object.warnings; + new_object.value_before_decode = util_copybuf(input_object.value_before_decode); + + return new_object; + } + // #endregion + + // #region Create a basic ASN.1 type since we need to return errors and warnings from the function + var return_object = new in_window.org.pkijs.asn1.ASN1_block(); + // #endregion + + // #region Basic check for parameters + if(check_buffer_params(input_buffer, input_offset, input_length) === false) + { + return_object.error = "Wrong input parameters"; + return { + offset: (-1), + result: return_object + }; + } + // #endregion + + // #region Getting Uint8Array from ArrayBuffer + var int_buffer = new Uint8Array(input_buffer, input_offset, input_length); + // #endregion + + // #region Initial checks + if(int_buffer.length == 0) + { + this.error = "Zero buffer length"; + return { + offset: (-1), + result: return_object + }; + } + // #endregion + + // #region Decode indentifcation block of ASN.1 BER structure + var result_offset = return_object.id_block.fromBER(input_buffer, input_offset, input_length); + return_object.warnings.concat(return_object.id_block.warnings); + if(result_offset == (-1)) + { + return_object.error = return_object.id_block.error; + return { + offset: (-1), + result: return_object + }; + } + + input_offset = result_offset; + input_length -= return_object.id_block.block_length; + // #endregion + + // #region Decode length block of ASN.1 BER structure + result_offset = return_object.len_block.fromBER(input_buffer, input_offset, input_length); + return_object.warnings.concat(return_object.len_block.warnings); + if(result_offset == (-1)) + { + return_object.error = return_object.len_block.error; + return { + offset: (-1), + result: return_object + }; + } + + input_offset = result_offset; + input_length -= return_object.len_block.block_length; + // #endregion + + // #region Check for usign indefinite length form in encoding for primitive types + if((return_object.id_block.is_constructed == false) && + (return_object.len_block.is_indefinite_form == true)) + { + return_object.error = new String("Indefinite length form used for primitive encoding form"); + return { + offset: (-1), + result: return_object + }; + } + // #endregion + + // #region Switch ASN.1 block type + var new_asn1_type = in_window.org.pkijs.asn1.ASN1_block; + + switch(return_object.id_block.tag_class) + { + // #region UNIVERSAL + case 1: + // #region Check for reserved tag numbers + if((return_object.id_block.tag_number >= 37) && + (return_object.id_block.is_hex_only == false)) + { + return_object.error = "UNIVERSAL 37 and upper tags are reserved by ASN.1 standard"; + return { + offset: (-1), + result: return_object + }; + } + // #endregion + + switch(return_object.id_block.tag_number) + { + // #region EOC type + case 0: + // #region Check for EOC type + if((return_object.id_block.is_constructed == true) && + (return_object.len_block.length > 0)) + { + return_object.error = "Type [UNIVERSAL 0] is reserved"; + return { + offset: (-1), + result: return_object + }; + } + // #endregion + + new_asn1_type = in_window.org.pkijs.asn1.EOC; + + break; + // #endregion + // #region BOOLEAN type + case 1: + new_asn1_type = in_window.org.pkijs.asn1.BOOLEAN; + break; + // #endregion + // #region INTEGER type + case 2: + new_asn1_type = in_window.org.pkijs.asn1.INTEGER; + break; + // #endregion + // #region BITSTRING type + case 3: + new_asn1_type = in_window.org.pkijs.asn1.BITSTRING; + break; + // #endregion + // #region OCTETSTRING type + case 4: + new_asn1_type = in_window.org.pkijs.asn1.OCTETSTRING; + break; + // #endregion + // #region NULL type + case 5: + new_asn1_type = in_window.org.pkijs.asn1.NULL; + break; + // #endregion + // #region OBJECT IDENTIFIER type + case 6: + new_asn1_type = in_window.org.pkijs.asn1.OID; + break; + // #endregion + // #region ENUMERATED type + case 10: + new_asn1_type = in_window.org.pkijs.asn1.ENUMERATED; + break; + // #endregion + // #region UTF8STRING type + case 12: + new_asn1_type = in_window.org.pkijs.asn1.UTF8STRING; + break; + // #endregion + // #region TIME type + case 14: + new_asn1_type = in_window.org.pkijs.asn1.TIME; + break; + // #endregion + // #region ASN.1 reserved type + case 15: + return_object.error = "[UNIVERSAL 15] is reserved by ASN.1 standard"; + return { + offset: (-1), + result: return_object + }; + break; + // #endregion + // #region SEQUENCE type + case 16: + new_asn1_type = in_window.org.pkijs.asn1.SEQUENCE; + break; + // #endregion + // #region SET type + case 17: + new_asn1_type = in_window.org.pkijs.asn1.SET; + break; + // #endregion + // #region NUMERICSTRING type + case 18: + new_asn1_type = in_window.org.pkijs.asn1.NUMERICSTRING; + break; + // #endregion + // #region PRINTABLESTRING type + case 19: + new_asn1_type = in_window.org.pkijs.asn1.PRINTABLESTRING; + break; + // #endregion + // #region TELETEXSTRING type + case 20: + new_asn1_type = in_window.org.pkijs.asn1.TELETEXSTRING; + break; + // #endregion + // #region VIDEOTEXSTRING type + case 21: + new_asn1_type = in_window.org.pkijs.asn1.VIDEOTEXSTRING; + break; + // #endregion + // #region IA5STRING type + case 22: + new_asn1_type = in_window.org.pkijs.asn1.IA5STRING; + break; + // #endregion + // #region UTCTIME type + case 23: + new_asn1_type = in_window.org.pkijs.asn1.UTCTIME; + break; + // #endregion + // #region GENERALIZEDTIME type + case 24: + new_asn1_type = in_window.org.pkijs.asn1.GENERALIZEDTIME; + break; + // #endregion + // #region GRAPHICSTRING type + case 25: + new_asn1_type = in_window.org.pkijs.asn1.GRAPHICSTRING; + break; + // #endregion + // #region VISIBLESTRING type + case 26: + new_asn1_type = in_window.org.pkijs.asn1.VISIBLESTRING; + break; + // #endregion + // #region GENERALSTRING type + case 27: + new_asn1_type = in_window.org.pkijs.asn1.GENERALSTRING; + break; + // #endregion + // #region UNIVERSALSTRING type + case 28: + new_asn1_type = in_window.org.pkijs.asn1.UNIVERSALSTRING; + break; + // #endregion + // #region CHARACTERSTRING type + case 29: + new_asn1_type = in_window.org.pkijs.asn1.CHARACTERSTRING; + break; + // #endregion + // #region BMPSTRING type + case 30: + new_asn1_type = in_window.org.pkijs.asn1.BMPSTRING; + break; + // #endregion + // #region DATE type + case 31: + new_asn1_type = in_window.org.pkijs.asn1.DATE; + break; + // #endregion + // #region TIMEOFDAY type + case 32: + new_asn1_type = in_window.org.pkijs.asn1.TIMEOFDAY; + break; + // #endregion + // #region DATE-TIME type + case 33: + new_asn1_type = in_window.org.pkijs.asn1.DATETIME; + break; + // #endregion + // #region DURATION type + case 34: + new_asn1_type = in_window.org.pkijs.asn1.DURATION; + break; + // #endregion + // #region default + default: + { + var new_object; + + if(return_object.id_block.is_constructed == true) + new_object = new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED(); + else + new_object = new in_window.org.pkijs.asn1.ASN1_PRIMITIVE(); + + new_object.id_block = return_object.id_block; + new_object.len_block = return_object.len_block; + new_object.warnings = return_object.warnings; + + return_object = new_object; + + result_offset = return_object.fromBER(input_buffer, input_offset, input_length); + } + // #endregion + } + break; + // #endregion + // #region All other tag classes + case 2: // APPLICATION + case 3: // CONTEXT-SPECIFIC + case 4: // PRIVATE + default: + { + if(return_object.id_block.is_constructed == true) + new_asn1_type = in_window.org.pkijs.asn1.ASN1_CONSTRUCTED; + else + new_asn1_type = in_window.org.pkijs.asn1.ASN1_PRIMITIVE; + } + // #endregion + } + // #endregion + + // #region Change type and perform BER decoding + return_object = local_change_type(return_object, new_asn1_type); + result_offset = return_object.fromBER(input_buffer, input_offset, (return_object.len_block.is_indefinite_form == true) ? input_length : return_object.len_block.length); + // #endregion + + // #region Coping incoming buffer for entire ASN.1 block + return_object.value_before_decode = util_copybuf_offset(input_buffer, incoming_offset, return_object.block_length); + // #endregion + + return { + offset: result_offset, + result: return_object + }; + } + //************************************************************************************** + in_window.org.pkijs.fromBER = + function(input_buffer) + { + /// Major function for decoding ASN.1 BER array into internal library structuries + /// ASN.1 BER encoded array of bytes + + if(input_buffer.byteLength == 0) + { + var result = new in_window.org.pkijs.asn1.ASN1_block(); + result.error = "Input buffer has zero length"; + + return { + offset: (-1), + result: result + }; + } + + return fromBER_raw(input_buffer, 0, input_buffer.byteLength); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Major scheme verification function + //************************************************************************************** + in_window.org.pkijs.compareSchema = + function(root, input_asn1_data, input_asn1_schema) + { + // #region Special case for CHOICE schema element type + if(input_asn1_schema instanceof in_window.org.pkijs.asn1.CHOICE) + { + var choice_result = false; + + for(var j = 0; j < input_asn1_schema.value.length; j++) + { + var result = in_window.org.pkijs.compareSchema(root, input_asn1_data, input_asn1_schema.value[j]); + if(result.verified === true) + return { + verified: true, + result: root + }; + } + + if(choice_result === false) + { + var _result = { + verified: false, + result: { + error: "Wrong values for CHOICE type" + } + }; + + if(input_asn1_schema.hasOwnProperty('name')) + _result.name = input_asn1_schema.name; + + return _result; + } + } + // #endregion + + // #region Special case for ANY schema element type + if(input_asn1_schema instanceof in_window.org.pkijs.asn1.ANY) + { + // #region Add named component of ASN.1 schema + if(input_asn1_schema.hasOwnProperty('name')) + root[input_asn1_schema.name] = input_asn1_data; + // #endregion + + return { + verified: true, + result: root + }; + } + // #endregion + + // #region Initial check + if((root instanceof Object) === false) + return { + verified: false, + result: { error: "Wrong root object" } + }; + + if((input_asn1_data instanceof Object) === false) + return { + verified: false, + result: { error: "Wrong ASN.1 data" } + }; + + if((input_asn1_schema instanceof Object) === false) + return { + verified: false, + result: { error: "Wrong ASN.1 schema" } + }; + + if(('id_block' in input_asn1_schema) === false) + return { + verified: false, + result: { error: "Wrong ASN.1 schema" } + }; + // #endregion + + // #region Comparing id_block properties in ASN.1 data and ASN.1 schema + // #region Encode and decode ASN.1 schema id_block + /// This encoding/decoding is neccessary because could be an errors in schema definition + if(('fromBER' in input_asn1_schema.id_block) === false) + return { + verified: false, + result: { error: "Wrong ASN.1 schema" } + }; + + if(('toBER' in input_asn1_schema.id_block) === false) + return { + verified: false, + result: { error: "Wrong ASN.1 schema" } + }; + + var encoded_id = input_asn1_schema.id_block.toBER(false); + if(encoded_id.byteLength === 0) + return { + verified: false, + result: { error: "Error encoding id_block for ASN.1 schema" } + }; + + var decoded_offset = input_asn1_schema.id_block.fromBER(encoded_id, 0, encoded_id.byteLength); + if(decoded_offset === (-1)) + return { + verified: false, + result: { error: "Error decoding id_block for ASN.1 schema" } + }; + // #endregion + + // #region tag_class + if(input_asn1_schema.id_block.hasOwnProperty('tag_class') === false) + return { + verified: false, + result: { error: "Wrong ASN.1 schema" } + }; + + if(input_asn1_schema.id_block.tag_class !== input_asn1_data.id_block.tag_class) + return { + verified: false, + result: root + }; + // #endregion + // #region tag_number + if(input_asn1_schema.id_block.hasOwnProperty('tag_number') === false) + return { + verified: false, + result: { error: "Wrong ASN.1 schema" } + }; + + if(input_asn1_schema.id_block.tag_number !== input_asn1_data.id_block.tag_number) + return { + verified: false, + result: root + }; + // #endregion + // #region is_constructed + if(input_asn1_schema.id_block.hasOwnProperty('is_constructed') === false) + return { + verified: false, + result: { error: "Wrong ASN.1 schema" } + }; + + if(input_asn1_schema.id_block.is_constructed !== input_asn1_data.id_block.is_constructed) + return { + verified: false, + result: root + }; + // #endregion + // #region is_hex_only + if(('is_hex_only' in input_asn1_schema.id_block) === false) // Since 'is_hex_only' is an inhirited property + return { + verified: false, + result: { error: "Wrong ASN.1 schema" } + }; + + if(input_asn1_schema.id_block.is_hex_only !== input_asn1_data.id_block.is_hex_only) + return { + verified: false, + result: root + }; + // #endregion + // #region value_hex + if(input_asn1_schema.id_block.is_hex_only === true) + { + if(('value_hex' in input_asn1_schema.id_block) === false) // Since 'value_hex' is an inhirited property + return { + verified: false, + result: { error: "Wrong ASN.1 schema" } + }; + + var schema_view = new Uint8Array(input_asn1_schema.id_block.value_hex); + var asn1_view = new Uint8Array(input_asn1_data.id_block.value_hex); + + if(schema_view.length !== asn1_view.length) + return { + verified: false, + result: root + }; + + for(var i = 0; i < schema_view.length; i++) + { + if(schema_view[i] !== asn1_view[1]) + return { + verified: false, + result: root + }; + } + } + // #endregion + // #endregion + + // #region Add named component of ASN.1 schema + if(input_asn1_schema.hasOwnProperty('name')) + { + input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, ''); + if(input_asn1_schema.name !== "") + root[input_asn1_schema.name] = input_asn1_data; + } + // #endregion + + // #region Getting next ASN.1 block for comparition + if(input_asn1_schema.id_block.is_constructed === true) + { + var admission = 0; + var result = { verified: false }; + + var max_length = input_asn1_schema.value_block.value.length; + + if(max_length > 0) + { + if(input_asn1_schema.value_block.value[0] instanceof in_window.org.pkijs.asn1.REPEATED) + max_length = input_asn1_data.value_block.value.length; + } + + // #region Special case when constructive value has no elements + if(max_length === 0) + return { + verified: true, + result: root + }; + // #endregion + + // #region Special case when "input_asn1_data" has no values and "input_asn1_schema" has all optional values + if((input_asn1_data.value_block.value.length === 0) && + (input_asn1_schema.value_block.value.length !== 0)) + { + var _optional = true; + + for(var i = 0; i < input_asn1_schema.value_block.value.length; i++) + _optional = _optional && (input_asn1_schema.value_block.value[i].optional || false); + + if(_optional === true) + { + return { + verified: true, + result: root + }; + } + else + { + // #region Delete early added name of block + if(input_asn1_schema.hasOwnProperty('name')) + { + input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, ''); + if(input_asn1_schema.name !== "") + delete root[input_asn1_schema.name]; + } + // #endregion + + root.error = "Inconsistent object length"; + + return { + verified: false, + result: root + }; + } + } + // #endregion + + for(var i = 0; i < max_length; i++) + { + // #region Special case when there is an "optional" element of ASN.1 schema at the end + if((i - admission) >= input_asn1_data.value_block.value.length) + { + if(input_asn1_schema.value_block.value[i].optional === false) + { + var _result = { + verified: false, + result: root + }; + + root.error = "Inconsistent length between ASN.1 data and schema"; + + // #region Delete early added name of block + if(input_asn1_schema.hasOwnProperty('name')) + { + input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, ''); + if(input_asn1_schema.name !== "") + { + delete root[input_asn1_schema.name]; + _result.name = input_asn1_schema.name; + } + } + // #endregion + + return _result; + } + } + // #endregion + else + { + // #region Special case for REPEATED type of ASN.1 schema element + if(input_asn1_schema.value_block.value[0] instanceof in_window.org.pkijs.asn1.REPEATED) + { + result = in_window.org.pkijs.compareSchema(root, input_asn1_data.value_block.value[i], input_asn1_schema.value_block.value[0].value); + if(result.verified === false) + { + if(input_asn1_schema.value_block.value[0].optional === true) + admission++; + else + { + // #region Delete early added name of block + if(input_asn1_schema.hasOwnProperty('name')) + { + input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, ''); + if(input_asn1_schema.name !== "") + delete root[input_asn1_schema.name]; + } + // #endregion + + return result; + } + } + + if(("name" in input_asn1_schema.value_block.value[0]) && (input_asn1_schema.value_block.value[0].name.length > 0)) + { + var array_root = {}; + + if(("local" in input_asn1_schema.value_block.value[0]) && (input_asn1_schema.value_block.value[0].local === true)) + array_root = input_asn1_data; + else + array_root = root; + + if(typeof array_root[input_asn1_schema.value_block.value[0].name] === "undefined") + array_root[input_asn1_schema.value_block.value[0].name] = new Array(); + + array_root[input_asn1_schema.value_block.value[0].name].push(input_asn1_data.value_block.value[i]); + } + } + // #endregion + else + { + result = in_window.org.pkijs.compareSchema(root, input_asn1_data.value_block.value[i - admission], input_asn1_schema.value_block.value[i]); + if(result.verified === false) + { + if(input_asn1_schema.value_block.value[i].optional === true) + admission++; + else + { + // #region Delete early added name of block + if(input_asn1_schema.hasOwnProperty('name')) + { + input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, ''); + if(input_asn1_schema.name !== "") + delete root[input_asn1_schema.name]; + } + // #endregion + + return result; + } + } + } + } + } + + if(result.verified === false) // The situation may take place if last element is "optional" and verification failed + { + var _result = { + verified: false, + result: root + }; + + // #region Delete early added name of block + if(input_asn1_schema.hasOwnProperty('name')) + { + input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, ''); + if(input_asn1_schema.name !== "") + { + delete root[input_asn1_schema.name]; + _result.name = input_asn1_schema.name; + } + } + // #endregion + + return _result; + } + + return { + verified: true, + result: root + }; + } + // #endregion + // #region Ability to parse internal value for primitive-encoded value (value of OCTETSTRING, for example) + else + { + if( ("primitive_schema" in input_asn1_schema) && + ("value_hex" in input_asn1_data.value_block) ) + { + // #region Decoding of raw ASN.1 data + var asn1 = in_window.org.pkijs.fromBER(input_asn1_data.value_block.value_hex); + if(asn1.offset === (-1)) + { + var _result = { + verified: false, + result: asn1.result + }; + + // #region Delete early added name of block + if(input_asn1_schema.hasOwnProperty('name')) + { + input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, ''); + if(input_asn1_schema.name !== "") + { + delete root[input_asn1_schema.name]; + _result.name = input_asn1_schema.name; + } + } + // #endregion + + return _result; + } + // #endregion + + return in_window.org.pkijs.compareSchema(root, asn1.result, input_asn1_schema.primitive_schema); + } + else + return { + verified: true, + result: root + }; + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.verifySchema = + function(input_buffer, input_schema) + { + // #region Initial check + if((input_schema instanceof Object) === false) + return { + verified: false, + result: { error: "Wrong ASN.1 schema type" } + }; + // #endregion + + // #region Decoding of raw ASN.1 data + var asn1 = in_window.org.pkijs.fromBER(input_buffer); + if(asn1.offset === (-1)) + return { + verified: false, + result: asn1.result + }; + // #endregion + + // #region Compare ASN.1 struct with input schema + return in_window.org.pkijs.compareSchema(asn1.result, asn1.result, input_schema); + // #endregion + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Major function converting JSON to ASN.1 objects + //************************************************************************************** + in_window.org.pkijs.fromJSON = + function(json) + { + /// Converting from JSON to ASN.1 objects + /// JSON string or object to convert to ASN.1 objects + }; + //************************************************************************************** + // #endregion + //************************************************************************************** +} +)(typeof exports !== "undefined" ? exports : window); \ No newline at end of file diff --git a/express-server/node_modules/asn1js/org/pkijs/common.js b/express-server/node_modules/asn1js/org/pkijs/common.js new file mode 100644 index 00000000..4d7b2e11 --- /dev/null +++ b/express-server/node_modules/asn1js/org/pkijs/common.js @@ -0,0 +1,1541 @@ +/* + * Copyright (c) 2014, GMO GlobalSign + * Copyright (c) 2015, Peculiar Ventures + * All rights reserved. + * + * Author 2014-2015, Yury Strozhevsky . + * + * 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 copyright holder 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. + * + */ +( +function(in_window) +{ + //************************************************************************************** + // #region Declaration of global variables + //************************************************************************************** + // #region "org" namespace + if(typeof in_window.org === "undefined") + in_window.org = {}; + else + { + if(typeof in_window.org !== "object") + throw new Error("Name org already exists and it's not an object"); + } + // #endregion + + // #region "org.pkijs" namespace + if(typeof in_window.org.pkijs === "undefined") + in_window.org.pkijs = {}; + else + { + if(typeof in_window.org.pkijs !== "object") + throw new Error("Name org.pkijs already exists and it's not an object" + " but " + (typeof in_window.org.pkijs)); + } + // #endregion + + // #region "local" namespace + var local = {}; + // #endregion + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Settings for "crypto engine" + //************************************************************************************** + local.engine = { + name: "none", + crypto: null, + subtle: null + }; + + if(typeof window != "undefined") + { + if("crypto" in window) + { + var engineName = "webcrypto"; + var cryptoObject = window.crypto; + var subtleObject = null; + + // Apple Safari support + if("webkitSubtle" in window.crypto) + subtleObject = window.crypto.webkitSubtle; + + if("subtle" in window.crypto) + subtleObject = window.crypto.subtle; + + local.engine = { + name: engineName, + crypto: cryptoObject, + subtle: subtleObject + }; + } + } + //************************************************************************************** + in_window.org.pkijs.setEngine = + function(name, crypto, subtle) + { + /// Setting the global "crypto engine" parameters + /// Auxiliary name for "crypto engine" + /// Object handling all root cryptographic requests (in fact currently it must handle only "getRandomValues") + /// Object handling all main cryptographic requests + + local.engine = { + name: name, + crypto: crypto, + subtle: subtle + }; + }; + //************************************************************************************** + in_window.org.pkijs.getEngine = + function() + { + return local.engine; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Declaration of common functions + //************************************************************************************** + in_window.org.pkijs.emptyObject = + function() + { + this.toJSON = function() + { + return {}; + }; + this.toSchema = function() + { + return {}; + }; + }; + //************************************************************************************** + in_window.org.pkijs.getNames = + function(arg) + { + /// Get correct "names" array for all "schema" objects + + var names = {}; + + if(arg instanceof Object) + names = (arg.names || {}); + + return names; + }; + //************************************************************************************** + in_window.org.pkijs.inheriteObjectFields = + function(from) + { + for(var i in from.prototype) + { + if(typeof from.prototype[i] === "function") + continue; + + this[i] = from.prototype[i]; + } + }; + //************************************************************************************** + in_window.org.pkijs.getUTCDate = + function(date) + { + /// Making UTC date from local date + /// Date to convert from + + var current_date = date; + return new Date(current_date.getTime() + (current_date.getTimezoneOffset() * 60000)); + }; + //************************************************************************************** + in_window.org.pkijs.padNumber = + function(input_number, full_length) + { + var str = input_number.toString(10); + var dif = full_length - str.length; + + var padding = new Array(dif); + for(var i = 0; i < dif; i++) + padding[i] = '0'; + + var padding_string = padding.join(''); + + return padding_string.concat(str); + }; + //************************************************************************************** + in_window.org.pkijs.getValue = + function(args, item, default_value) + { + if(item in args) + return args[item]; + else + return default_value; + }; + //************************************************************************************** + in_window.org.pkijs.isEqual_view = + function(input_view1, input_view2) + { + /// Compare two Uint8Arrays + /// First Uint8Array for comparision + /// Second Uint8Array for comparision + + if(input_view1.length !== input_view2.length) + return false; + + for(var i = 0; i < input_view1.length; i++) + { + if(input_view1[i] != input_view2[i]) + return false; + } + + return true; + }; + //************************************************************************************** + in_window.org.pkijs.isEqual_buffer = + function(input_buffer1, input_buffer2) + { + /// Compare two array buffers + /// First ArrayBuffer for comparision + /// Second ArrayBuffer for comparision + + if(input_buffer1.byteLength != input_buffer2.byteLength) + return false; + + var view1 = new Uint8Array(input_buffer1); + var view2 = new Uint8Array(input_buffer2); + + return in_window.org.pkijs.isEqual_view(view1, view2); + }; + //************************************************************************************** + in_window.org.pkijs.concat_buffers = + function(input_buf1, input_buf2) + { + /// Concatenate two ArrayBuffers + /// First ArrayBuffer (first part of concatenated array) + /// Second ArrayBuffer (second part of concatenated array) + + var input_view1 = new Uint8Array(input_buf1); + var input_view2 = new Uint8Array(input_buf2); + + var ret_buf = new ArrayBuffer(input_buf1.byteLength + input_buf2.byteLength); + var ret_view = new Uint8Array(ret_buf); + + for(var i = 0; i < input_buf1.byteLength; i++) + ret_view[i] = input_view1[i]; + + for(var j = 0; j < input_buf2.byteLength; j++) + ret_view[input_buf1.byteLength + j] = input_view2[j]; + + return ret_buf; + }; + //************************************************************************************** + in_window.org.pkijs.copyBuffer = + function(input_buffer) + { + var result = new ArrayBuffer(input_buffer.byteLength); + + var resultView = new Uint8Array(result); + var inputView = new Uint8Array(input_buffer); + + for(var i = 0; i < inputView.length; i++) + resultView[i] = inputView[i]; + + return result; + }; + //************************************************************************************** + in_window.org.pkijs.getCrypto = + function() + { + var crypto_temp; + + if(local.engine.subtle !== null) + crypto_temp = local.engine.subtle; + + return crypto_temp; + }; + //************************************************************************************** + in_window.org.pkijs.stringPrep = + function(input_string) + { + /// String preparation function. In a future here will be realization of algorithm from RFC4518. + /// JavaScript string. As soon as for each ASN.1 string type we have a specific transformation function here we will work with pure JavaScript string + /// Formated string + + var result = input_string.replace(/^\s+|\s+$/g, ""); // Trim input string + result = result.replace(/\s+/g, " "); // Change all sequence of SPACE down to SPACE char + result = result.toLowerCase(); + + return result; + }; + //************************************************************************************** + in_window.org.pkijs.bufferToHexCodes = + function(input_buffer, input_offset, input_lenght) + { + var result = ""; + + var int_buffer = new Uint8Array(input_buffer, input_offset, input_lenght); + + for(var i = 0; i < int_buffer.length; i++) + { + var str = int_buffer[i].toString(16).toUpperCase(); + result = result + ((str.length === 1) ? "0" : "") + str; + } + + return result; + }; + //************************************************************************************** + in_window.org.pkijs.bufferFromHexCodes = + function(hexString) + { + /// Create an ArrayBuffer from string having hexdecimal codes + /// String to create ArrayBuffer from + + // #region Initial variables + var stringLength = hexString.length; + + var resultBuffer = new ArrayBuffer(stringLength >> 1); + var resultView = new Uint8Array(resultBuffer); + + var hex_map = {}; + + hex_map['0'] = 0x00; + hex_map['1'] = 0x01; + hex_map['2'] = 0x02; + hex_map['3'] = 0x03; + hex_map['4'] = 0x04; + hex_map['5'] = 0x05; + hex_map['6'] = 0x06; + hex_map['7'] = 0x07; + hex_map['8'] = 0x08; + hex_map['9'] = 0x09; + hex_map['A'] = 0x0A; + hex_map['a'] = 0x0A; + hex_map['B'] = 0x0B; + hex_map['b'] = 0x0B; + hex_map['C'] = 0x0C; + hex_map['c'] = 0x0C; + hex_map['D'] = 0x0D; + hex_map['d'] = 0x0D; + hex_map['E'] = 0x0E; + hex_map['e'] = 0x0E; + hex_map['F'] = 0x0F; + hex_map['f'] = 0x0F; + + var j = 0; + var temp = 0x00; + // #endregion + + // #region Convert char-by-char + for(var i = 0; i < stringLength; i++) + { + if(!(i % 2)) + temp = hex_map[hexString.charAt(i)] << 4; + else + { + temp |= hex_map[hexString.charAt(i)]; + + resultView[j] = temp; + j++; + } + } + // #endregion + + return resultBuffer; + }; + //************************************************************************************** + in_window.org.pkijs.getRandomValues = + function(view) + { + /// New array which gives a length for random value + + if(local.engine.crypto !== null) + return local.engine.crypto.getRandomValues(view); + else + throw new Error("No support for Web Cryptography API"); + }; + //************************************************************************************** + in_window.org.pkijs.getAlgorithmParameters = + function(algorithmName, operation) + { + /// Algorithm name to get common parameters for + /// Kind of operation: "sign", "encrypt", "generatekey", "importkey", "exportkey", "verify" + + var result = { + algorithm: {}, + usages: [] + }; + + switch(algorithmName.toUpperCase()) + { + case "RSASSA-PKCS1-V1_5": + switch(operation.toLowerCase()) + { + case "generatekey": + result = { + algorithm: { + name: "RSASSA-PKCS1-v1_5", + modulusLength: 2048, + publicExponent: new Uint8Array([0x01, 0x00, 0x01]), + hash: { + name: "SHA-256" + } + }, + usages: ["sign", "verify"] + }; + break; + case "verify": + case "sign": + case "importkey": + result = { + algorithm: { + name: "RSASSA-PKCS1-v1_5", + hash: { + name: "SHA-256" + } + }, + usages: ["verify"] // For importKey("pkcs8") usage must be "sign" only + }; + break; + case "exportkey": + default: + return { + algorithm: { + name: "RSASSA-PKCS1-v1_5" + }, + usages: [] + }; + } + break; + case "RSA-PSS": + switch(operation.toLowerCase()) + { + case "sign": + case "verify": + result = { + algorithm: { + name: "RSA-PSS", + hash: { + name: "SHA-1" + }, + saltLength: 20 + }, + usages: ["sign", "verify"] + }; + break; + case "generatekey": + result = { + algorithm: { + name: "RSA-PSS", + modulusLength: 2048, + publicExponent: new Uint8Array([0x01, 0x00, 0x01]), + hash: { + name: "SHA-1" + } + }, + usages: ["sign", "verify"] + }; + break; + case "importkey": + result = { + algorithm: { + name: "RSA-PSS", + hash: { + name: "SHA-1" + } + }, + usages: ["verify"] // For importKey("pkcs8") usage must be "sign" only + }; + break; + case "exportkey": + default: + return { + algorithm: { + name: "RSA-PSS" + }, + usages: [] + }; + } + break; + case "RSA-OAEP": + switch(operation.toLowerCase()) + { + case "encrypt": + case "decrypt": + result = { + algorithm: { + name: "RSA-OAEP" + }, + usages: ["encrypt", "decrypt"] + }; + break; + break; + case "generatekey": + result = { + algorithm: { + name: "RSA-OAEP", + modulusLength: 2048, + publicExponent: new Uint8Array([0x01, 0x00, 0x01]), + hash: { + name: "SHA-256" + } + }, + usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"] + }; + break; + case "importkey": + result = { + algorithm: { + name: "RSA-OAEP", + hash: { + name: "SHA-256" + } + }, + usages: ["encrypt"] // encrypt for "spki" and decrypt for "pkcs8" + }; + break; + case "exportkey": + default: + return { + algorithm: { + name: "RSA-OAEP" + }, + usages: [] + }; + } + break; + case "ECDSA": + switch(operation.toLowerCase()) + { + case "generatekey": + result = { + algorithm: { + name: "ECDSA", + namedCurve: "P-256" + }, + usages: ["sign", "verify"] + }; + break; + case "importkey": + result = { + algorithm: { + name: "ECDSA", + namedCurve: "P-256" + }, + usages: ["verify"] // "sign" for "pkcs8" + }; + break; + case "verify": + case "sign": + result = { + algorithm: { + name: "ECDSA", + hash: { + name: "SHA-256" + } + }, + usages: ["sign"] + }; + break; + default: + return { + algorithm: { + name: "ECDSA" + }, + usages: [] + }; + } + break; + case "ECDH": + switch(operation.toLowerCase()) + { + case "exportkey": + case "importkey": + case "generatekey": + result = { + algorithm: { + name: "ECDH", + namedCurve: "P-256" + }, + usages: ["deriveKey", "deriveBits"] + }; + break; + case "derivekey": + case "derivebits": + result = { + algorithm: { + name: "ECDH", + namedCurve: "P-256", + public: [] // Must be a "publicKey" + }, + usages: ["encrypt", "decrypt"] + }; + break; + default: + return { + algorithm: { + name: "ECDH" + }, + usages: [] + }; + } + break; + case "AES-CTR": + switch(operation.toLowerCase()) + { + case "importkey": + case "exportkey": + case "generatekey": + result = { + algorithm: { + name: "AES-CTR", + length: 256 + }, + usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"] + }; + break; + case "decrypt": + case "encrypt": + result = { + algorithm: { + name: "AES-CTR", + counter: new Uint8Array(16), + length: 10 + }, + usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"] + }; + break; + default: + return { + algorithm: { + name: "AES-CTR" + }, + usages: [] + }; + } + break; + case "AES-CBC": + switch(operation.toLowerCase()) + { + case "importkey": + case "exportkey": + case "generatekey": + result = { + algorithm: { + name: "AES-CBC", + length: 256 + }, + usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"] + }; + break; + case "decrypt": + case "encrypt": + result = { + algorithm: { + name: "AES-CBC", + iv: in_window.org.pkijs.getRandomValues(new Uint8Array(16)) // For "decrypt" the value should be replaced with value got on "encrypt" step + }, + usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"] + }; + break; + default: + return { + algorithm: { + name: "AES-CBC" + }, + usages: [] + }; + } + break; + case "AES-GCM": + switch(operation.toLowerCase()) + { + case "importkey": + case "exportkey": + case "generatekey": + result = { + algorithm: { + name: "AES-GCM", + length: 256 + }, + usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"] + }; + break; + case "decrypt": + case "encrypt": + result = { + algorithm: { + name: "AES-GCM", + iv: in_window.org.pkijs.getRandomValues(new Uint8Array(16)) // For "decrypt" the value should be replaced with value got on "encrypt" step + }, + usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"] + }; + break; + default: + return { + algorithm: { + name: "AES-GCM" + }, + usages: [] + }; + } + break; + case "AES-KW": + switch(operation.toLowerCase()) + { + case "importkey": + case "exportkey": + case "generatekey": + case "wrapkey": + case "unwrapkey": + result = { + algorithm: { + name: "AES-KW", + length: 256 + }, + usages: ["wrapKey", "unwrapKey"] + }; + break; + default: + return { + algorithm: { + name: "AES-KW" + }, + usages: [] + }; + } + break; + case "HMAC": + switch(operation.toLowerCase()) + { + case "sign": + case "verify": + result = { + algorithm: { + name: "HMAC" + }, + usages: ["sign", "verify"] + }; + break; + case "importkey": + case "exportkey": + case "generatekey": + result = { + algorithm: { + name: "HMAC", + length: 32, + hash: { + name: "SHA-256" + } + }, + usages: ["sign", "verify"] + }; + break; + default: + return { + algorithm: { + name: "HMAC" + }, + usages: [] + }; + } + break; + case "HKDF": + switch(operation.toLowerCase()) + { + case "derivekey": + result = { + algorithm: { + name: "HKDF", + hash: "SHA-256", + salt: new Uint8Array(), + info: new Uint8Array() + }, + usages: ["encrypt", "decrypt"] + }; + break; + default: + return { + algorithm: { + name: "HKDF" + }, + usages: [] + }; + } + break; + case "PBKDF2": + switch(operation.toLowerCase()) + { + case "derivekey": + result = { + algorithm: { + name: "PBKDF2", + hash: { name: "SHA-256" }, + salt: new Uint8Array(), + iterations: 1000 + }, + usages: ["encrypt", "decrypt"] + }; + break; + default: + return { + algorithm: { + name: "PBKDF2" + }, + usages: [] + }; + } + break; + default: + ; + } + + return result; + }; + //************************************************************************************** + in_window.org.pkijs.getOIDByAlgorithm = + function(algorithm) + { + /// Get OID for each specific WebCrypto algorithm + /// WebCrypto algorithm + + var result = ""; + + switch(algorithm.name.toUpperCase()) + { + case "RSASSA-PKCS1-V1_5": + switch(algorithm.hash.name.toUpperCase()) + { + case "SHA-1": + result = "1.2.840.113549.1.1.5"; + break; + case "SHA-256": + result = "1.2.840.113549.1.1.11"; + break; + case "SHA-384": + result = "1.2.840.113549.1.1.12"; + break; + case "SHA-512": + result = "1.2.840.113549.1.1.13"; + break; + default:; + } + break; + case "RSA-PSS": + result = "1.2.840.113549.1.1.10"; + break; + case "RSA-OAEP": + result = "1.2.840.113549.1.1.7"; + break; + case "ECDSA": + switch(algorithm.hash.name.toUpperCase()) + { + case "SHA-1": + result = "1.2.840.10045.4.1"; + break; + case "SHA-256": + result = "1.2.840.10045.4.3.2"; + break; + case "SHA-384": + result = "1.2.840.10045.4.3.3"; + break; + case "SHA-512": + result = "1.2.840.10045.4.3.4"; + break; + default:; + } + break; + case "ECDH": + switch(algorithm.kdf.toUpperCase()) // Non-standard addition - hash algorithm of KDF function + { + case "SHA-1": + result = "1.3.133.16.840.63.0.2"; // dhSinglePass-stdDH-sha1kdf-scheme + break; + case "SHA-256": + result = "1.3.132.1.11.1"; // dhSinglePass-stdDH-sha256kdf-scheme + break; + case "SHA-384": + result = "1.3.132.1.11.2"; // dhSinglePass-stdDH-sha384kdf-scheme + break; + case "SHA-512": + result = "1.3.132.1.11.3"; // dhSinglePass-stdDH-sha512kdf-scheme + break; + default:; + } + break; + case "AES-CTR": + break; + case "AES-CBC": + switch(algorithm.length) + { + case 128: + result = "2.16.840.1.101.3.4.1.2"; + break; + case 192: + result = "2.16.840.1.101.3.4.1.22"; + break; + case 256: + result = "2.16.840.1.101.3.4.1.42"; + break; + default:; + } + break; + case "AES-CMAC": + break; + case "AES-GCM": + switch(algorithm.length) + { + case 128: + result = "2.16.840.1.101.3.4.1.6"; + break; + case 192: + result = "2.16.840.1.101.3.4.1.26"; + break; + case 256: + result = "2.16.840.1.101.3.4.1.46"; + break; + default:; + } + break; + case "AES-CFB": + switch(algorithm.length) + { + case 128: + result = "2.16.840.1.101.3.4.1.4"; + break; + case 192: + result = "2.16.840.1.101.3.4.1.24"; + break; + case 256: + result = "2.16.840.1.101.3.4.1.44"; + break; + default:; + } + break; + case "AES-KW": + switch(algorithm.length) + { + case 128: + result = "2.16.840.1.101.3.4.1.5"; + break; + case 192: + result = "2.16.840.1.101.3.4.1.25"; + break; + case 256: + result = "2.16.840.1.101.3.4.1.45"; + break; + default:; + } + break; + case "HMAC": + switch(algorithm.hash.name.toUpperCase()) + { + case "SHA-1": + result = "1.2.840.113549.2.7"; + break; + case "SHA-256": + result = "1.2.840.113549.2.9"; + break; + case "SHA-384": + result = "1.2.840.113549.2.10"; + break; + case "SHA-512": + result = "1.2.840.113549.2.11"; + break; + default:; + } + break; + case "DH": + result = "1.2.840.113549.1.9.16.3.5"; + break; + case "SHA-1": + result = "1.3.14.3.2.26"; + break; + case "SHA-256": + result = "2.16.840.1.101.3.4.2.1"; + break; + case "SHA-384": + result = "2.16.840.1.101.3.4.2.2"; + break; + case "SHA-512": + result = "2.16.840.1.101.3.4.2.3"; + break; + case "CONCAT": + break; + case "HKDF": + break; + case "PBKDF2": + result = "1.2.840.113549.1.5.12"; + break; + // #region Special case - OIDs for ECC curves + case "P-256": + result = "1.2.840.10045.3.1.7"; + break; + case "P-384": + result = "1.3.132.0.34"; + break; + case "P-521": + result = "1.3.132.0.35"; + break; + // #endregion + default:; + } + + return result; + }; + //************************************************************************************** + in_window.org.pkijs.getAlgorithmByOID = + function(oid) + { + /// Get WebCrypto algorithm by wel-known OID + /// Wel-known OID to search for + + var result = {}; + + switch(oid) + { + case "1.2.840.113549.1.1.5": + result = { + name: "RSASSA-PKCS1-v1_5", + hash: { + name: "SHA-1" + } + }; + break; + case "1.2.840.113549.1.1.11": + result = { + name: "RSASSA-PKCS1-v1_5", + hash: { + name: "SHA-256" + } + }; + break; + case "1.2.840.113549.1.1.12": + result = { + name: "RSASSA-PKCS1-v1_5", + hash: { + name: "SHA-384" + } + }; + break; + case "1.2.840.113549.1.1.13": + result = { + name: "RSASSA-PKCS1-v1_5", + hash: { + name: "SHA-512" + } + }; + break; + case "1.2.840.113549.1.1.10": + result = { + name: "RSA-PSS" + }; + break; + case "1.2.840.113549.1.1.7": + result = { + name: "RSA-OAEP" + }; + break; + case "1.2.840.10045.4.1": + result = { + name: "ECDSA", + hash: { + name: "SHA-1" + } + }; + break; + case "1.2.840.10045.4.3.2": + result = { + name: "ECDSA", + hash: { + name: "SHA-256" + } + }; + break; + case "1.2.840.10045.4.3.3": + result = { + name: "ECDSA", + hash: { + name: "SHA-384" + } + }; + break; + case "1.2.840.10045.4.3.4": + result = { + name: "ECDSA", + hash: { + name: "SHA-512" + } + }; + break; + case "1.3.133.16.840.63.0.2": + result = { + name: "ECDH", + kdf: "SHA-1" + }; + break; + case "1.3.132.1.11.1": + result = { + name: "ECDH", + kdf: "SHA-256" + }; + break; + case "1.3.132.1.11.2": + result = { + name: "ECDH", + kdf: "SHA-384" + }; + break; + case "1.3.132.1.11.3": + result = { + name: "ECDH", + kdf: "SHA-512" + }; + break; + case "2.16.840.1.101.3.4.1.2": + result = { + name: "AES-CBC", + length: 128 + }; + break; + case "2.16.840.1.101.3.4.1.22": + result = { + name: "AES-CBC", + length: 192 + }; + break; + case "2.16.840.1.101.3.4.1.42": + result = { + name: "AES-CBC", + length: 256 + }; + break; + case "2.16.840.1.101.3.4.1.6": + result = { + name: "AES-GCM", + length: 128 + }; + break; + case "2.16.840.1.101.3.4.1.26": + result = { + name: "AES-GCM", + length: 192 + }; + break; + case "2.16.840.1.101.3.4.1.46": + result = { + name: "AES-GCM", + length: 256 + }; + break; + case "2.16.840.1.101.3.4.1.4": + result = { + name: "AES-CFB", + length: 128 + }; + break; + case "2.16.840.1.101.3.4.1.24": + result = { + name: "AES-CFB", + length: 192 + }; + break; + case "2.16.840.1.101.3.4.1.44": + result = { + name: "AES-CFB", + length: 256 + }; + break; + case "2.16.840.1.101.3.4.1.5": + result = { + name: "AES-KW", + length: 128 + }; + break; + case "2.16.840.1.101.3.4.1.25": + result = { + name: "AES-KW", + length: 192 + }; + break; + case "2.16.840.1.101.3.4.1.45": + result = { + name: "AES-KW", + length: 256 + }; + break; + case "1.2.840.113549.2.7": + result = { + name: "HMAC", + hash: { + name: "SHA-1" + } + }; + break; + case "1.2.840.113549.2.9": + result = { + name: "HMAC", + hash: { + name: "SHA-256" + } + }; + break; + case "1.2.840.113549.2.10": + result = { + name: "HMAC", + hash: { + name: "SHA-384" + } + }; + break; + case "1.2.840.113549.2.11": + result = { + name: "HMAC", + hash: { + name: "SHA-512" + } + }; + break; + case "1.2.840.113549.1.9.16.3.5": + result = { + name: "DH" + }; + break; + case "1.3.14.3.2.26": + result = { + name: "SHA-1" + }; + break; + case "2.16.840.1.101.3.4.2.1": + result = { + name: "SHA-256" + }; + break; + case "2.16.840.1.101.3.4.2.2": + result = { + name: "SHA-384" + }; + break; + case "2.16.840.1.101.3.4.2.3": + result = { + name: "SHA-512" + }; + break; + case "1.2.840.113549.1.5.12": + result = { + name: "PBKDF2" + }; + break; + // #region Special case - OIDs for ECC curves + case "1.2.840.10045.3.1.7": + result = { + name: "P-256" + }; + break; + case "1.3.132.0.34": + result = { + name: "P-384" + }; + break; + case "1.3.132.0.35": + result = { + name: "P-521" + }; + break; + // #endregion + default:; + } + + return result; + }; + //************************************************************************************** + in_window.org.pkijs.getHashAlgorithm = + function(signatureAlgorithm) + { + /// Getting hash algorithm by signature algorithm + /// Signature algorithm + + var result = ""; + + switch(signatureAlgorithm.algorithm_id) + { + case "1.2.840.10045.4.1": // ecdsa-with-SHA1 + case "1.2.840.113549.1.1.5": + result = "SHA-1"; + break; + case "1.2.840.10045.4.3.2": // ecdsa-with-SHA256 + case "1.2.840.113549.1.1.11": + result = "SHA-256"; + break; + case "1.2.840.10045.4.3.3": // ecdsa-with-SHA384 + case "1.2.840.113549.1.1.12": + result = "SHA-384"; + break; + case "1.2.840.10045.4.3.4": // ecdsa-with-SHA512 + case "1.2.840.113549.1.1.13": + result = "SHA-512"; + break; + case "1.2.840.113549.1.1.10": // RSA-PSS + { + var params; + + try + { + params = new in_window.org.pkijs.simpl.x509.RSASSA_PSS_params({ schema: signatureAlgorithm.algorithm_params }); + if("hashAlgorithm" in params) + { + var algorithm = in_window.org.pkijs.getAlgorithmByOID(params.hashAlgorithm.algorithm_id); + if(("name" in algorithm) === false) + return ""; + + result = algorithm.name; + } + else + result = "SHA-1"; + } + catch(ex) + { + } + } + break; + default:; + } + + return result; + }; + //************************************************************************************** + in_window.org.pkijs.createCMSECDSASignature = + function(signatureBuffer) + { + /// Create CMS ECDSA signature from WebCrypto ECDSA signature + /// WebCrypto result of "sign" function + + // #region Initial check for correct length + if((signatureBuffer.byteLength % 2) != 0) + return new ArrayBuffer(0); + // #endregion + + // #region Initial variables + var i = 0; + var length = signatureBuffer.byteLength / 2; // There are two equal parts inside incoming ArrayBuffer + + var signatureView = new Uint8Array(signatureBuffer); + + var r_buffer = new ArrayBuffer(length); + var r_view = new Uint8Array(r_buffer); + var r_corrected_buffer; + var r_corrected_view; + + var s_buffer = new ArrayBuffer(length); + var s_view = new Uint8Array(s_buffer); + var s_corrected_buffer; + var s_corrected_view; + // #endregion + + // #region Get "r" part of ECDSA signature + for(; i < length; i++) + r_view[i] = signatureView[i]; + + if(r_view[0] & 0x80) + { + r_corrected_buffer = new ArrayBuffer(length + 1); + r_corrected_view = new Uint8Array(r_corrected_buffer); + + r_corrected_view[0] = 0x00; + + for(var j = 0; j < length; j++) + r_corrected_view[j + 1] = r_view[j]; + } + else + { + r_corrected_buffer = r_buffer; + r_corrected_view = r_view; + } + // #endregion + + // #region Get "s" part of ECDSA signature + for(; i < signatureBuffer.byteLength; i++) + s_view[i - length] = signatureView[i]; + + + if(s_view[0] & 0x80) + { + s_corrected_buffer = new ArrayBuffer(length + 1); + s_corrected_view = new Uint8Array(s_corrected_buffer); + + s_corrected_view[0] = 0x00; + + for(var j = 0; j < length; j++) + s_corrected_view[j + 1] = s_view[j]; + } + else + { + s_corrected_buffer = s_buffer; + s_corrected_view = s_view; + } + // #endregion + + // #region Create ASN.1 structure of CMS ECDSA signature + var r_integer = new in_window.org.pkijs.asn1.INTEGER(); + r_integer.value_block.is_hex_only = true; + r_integer.value_block.value_hex = in_window.org.pkijs.copyBuffer(r_corrected_buffer); + + var s_integer = new in_window.org.pkijs.asn1.INTEGER(); + s_integer.value_block.is_hex_only = true; + s_integer.value_block.value_hex = in_window.org.pkijs.copyBuffer(s_corrected_buffer); + + var asn1 = new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + r_integer, + s_integer + ] + }); + // #endregion + + return asn1.toBER(false); + }; + //************************************************************************************** + in_window.org.pkijs.createECDSASignatureFromCMS = + function(cmsSignature) + { + /// Create a single ArrayBuffer from CMS ECDSA signature + /// ASN.1 SEQUENCE contains CMS ECDSA signature + + // #region Initial variables + var length = 0; + + var r_start = 0; + var s_start = 0; + + var r_length = cmsSignature.value_block.value[0].value_block.value_hex.byteLength; + var s_length = cmsSignature.value_block.value[1].value_block.value_hex.byteLength; + // #endregion + + // #region Get length of final "ArrayBuffer" + var r_view = new Uint8Array(cmsSignature.value_block.value[0].value_block.value_hex); + if((r_view[0] === 0x00) && (r_view[1] & 0x80)) + { + length = r_length - 1; + r_start = 1; + } + else + length = r_length; + + var s_view = new Uint8Array(cmsSignature.value_block.value[1].value_block.value_hex); + if((s_view[0] === 0x00) && (s_view[1] & 0x80)) + { + length += s_length - 1; + s_start = 1; + } + else + length += s_length; + // #endregion + + // #region Copy values from CMS ECDSA signature + var result = new ArrayBuffer(length); + var result_view = new Uint8Array(result); + + for(var i = r_start; i < r_length; i++) + result_view[i - r_start] = r_view[i]; + + for(var i = s_start; i < s_length; i++) + result_view[i - s_start + r_length - r_start] = s_view[i]; + // #endregion + + return result; + }; + //************************************************************************************** + in_window.org.pkijs.getEncryptionAlgorithm = + function(algorithm) + { + /// Get encryption algorithm OID by WebCrypto algorithm's object + /// WebCrypto algorithm object + + var result = ""; + + switch(algorithm.name.toUpperCase()) + { + case "AES-CBC": + switch(algorithm.length) + { + case 128: + result = "2.16.840.1.101.3.4.1.2"; + break; + case 192: + result = "2.16.840.1.101.3.4.1.22"; + break; + case 256: + result = "2.16.840.1.101.3.4.1.42"; + break; + default:; + } + break; + case "AES-GCM": + switch(algorithm.length) + { + case 128: + result = "2.16.840.1.101.3.4.1.6"; + break; + case 192: + result = "2.16.840.1.101.3.4.1.26"; + break; + case 256: + result = "2.16.840.1.101.3.4.1.46"; + break; + default:; + } + break; + default:; + } + + return result; + }; + //************************************************************************************** + in_window.org.pkijs.getAlgorithmByEncryptionOID = + function(oid) + { + /// Get encryption algorithm name by OID + /// OID of encryption algorithm + + var result = ""; + + switch(oid) + { + case "2.16.840.1.101.3.4.1.2": + case "2.16.840.1.101.3.4.1.22": + case "2.16.840.1.101.3.4.1.42": + result = "AES-CBC"; + break; + case "2.16.840.1.101.3.4.1.6": + case "2.16.840.1.101.3.4.1.26": + case "2.16.840.1.101.3.4.1.46": + result = "AES-GCM"; + break; + default:; + } + + return result; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** +} +)(typeof exports !== "undefined" ? exports : window); \ No newline at end of file diff --git a/express-server/node_modules/asn1js/package.json b/express-server/node_modules/asn1js/package.json new file mode 100644 index 00000000..4386aa36 --- /dev/null +++ b/express-server/node_modules/asn1js/package.json @@ -0,0 +1,94 @@ +{ + "_args": [ + [ + "asn1js@^1.2.12", + "/nodeapps/https-test/greenlock-express.js/node_modules/certpem" + ] + ], + "_from": "asn1js@>=1.2.12 <2.0.0", + "_id": "asn1js@1.2.12", + "_inCache": true, + "_installable": true, + "_location": "/asn1js", + "_nodeVersion": "5.8.0", + "_npmOperationalInternal": { + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/asn1js-1.2.12.tgz_1460549801979_0.2164379085879773" + }, + "_npmUser": { + "email": "yury@strozhevsky.com", + "name": "yury.strozhevsky" + }, + "_npmVersion": "3.7.3", + "_phantomChildren": {}, + "_requested": { + "name": "asn1js", + "raw": "asn1js@^1.2.12", + "rawSpec": "^1.2.12", + "scope": null, + "spec": ">=1.2.12 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/certpem" + ], + "_resolved": "https://registry.npmjs.org/asn1js/-/asn1js-1.2.12.tgz", + "_shasum": "87d5ee797596ae2d2a3cb0247220dc42ffc3f211", + "_shrinkwrap": null, + "_spec": "asn1js@^1.2.12", + "_where": "/nodeapps/https-test/greenlock-express.js/node_modules/certpem", + "author": { + "email": "yury@strozhevsky.com", + "name": "Yury Strozhevsky" + }, + "bugs": { + "url": "https://github.com/GlobalSign/ASN1.js/issues" + }, + "contributors": [ + { + "name": "Ryan Hurst", + "email": "rmh@unmitigatedrisk.com" + } + ], + "dependencies": {}, + "description": "ASN1js is a pure JavaScript library implementing this standard. ASN.1 is the basis of all X.509 related data structures and numerous other protocols used on the web", + "devDependencies": {}, + "directories": {}, + "dist": { + "shasum": "87d5ee797596ae2d2a3cb0247220dc42ffc3f211", + "tarball": "https://registry.npmjs.org/asn1js/-/asn1js-1.2.12.tgz" + }, + "gitHead": "766534d2109c0e9ccc72d9b094eef50efe007925", + "homepage": "https://github.com/GlobalSign/ASN1.js#readme", + "keywords": [ + "asn.1", + "asn1", + "ber", + "bitstring", + "bmpstring", + "der", + "generalizedtime", + "octetstring", + "sequence", + "set", + "universalstring", + "utctime", + "utf8string" + ], + "main": "org/pkijs/asn1.js", + "maintainers": [ + { + "name": "yury.strozhevsky", + "email": "yury@strozhevsky.com" + } + ], + "name": "asn1js", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/GlobalSign/ASN1.js.git" + }, + "scripts": {}, + "version": "1.2.12" +} diff --git a/express-server/node_modules/async-limiter/.travis.yml b/express-server/node_modules/async-limiter/.travis.yml new file mode 100644 index 00000000..6cf4a7ad --- /dev/null +++ b/express-server/node_modules/async-limiter/.travis.yml @@ -0,0 +1,7 @@ +language: node_js +node_js: + - "6" + - "node" +script: npm run travis +cache: + yarn: true diff --git a/express-server/node_modules/async-limiter/LICENSE b/express-server/node_modules/async-limiter/LICENSE new file mode 100644 index 00000000..9c91fb26 --- /dev/null +++ b/express-server/node_modules/async-limiter/LICENSE @@ -0,0 +1,8 @@ +The MIT License (MIT) +Copyright (c) 2017 Samuel Reed + +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/express-server/node_modules/async-limiter/coverage/coverage.json b/express-server/node_modules/async-limiter/coverage/coverage.json new file mode 100644 index 00000000..5b4a3584 --- /dev/null +++ b/express-server/node_modules/async-limiter/coverage/coverage.json @@ -0,0 +1 @@ +{"/Users/samuelreed/git/forks/async-throttle/index.js":{"path":"/Users/samuelreed/git/forks/async-throttle/index.js","s":{"1":1,"2":7,"3":1,"4":6,"5":6,"6":6,"7":6,"8":6,"9":6,"10":1,"11":1,"12":3,"13":13,"14":13,"15":13,"16":1,"17":19,"18":1,"19":45,"20":6,"21":39,"22":13,"23":13,"24":13,"25":13,"26":39,"27":18,"28":6,"29":6,"30":1,"31":6,"32":6,"33":6,"34":1,"35":13,"36":13,"37":1},"b":{"1":[1,6],"2":[6,5],"3":[6,5],"4":[6,39],"5":[13,26],"6":[18,21],"7":[6,0]},"f":{"1":7,"2":3,"3":13,"4":19,"5":45,"6":6,"7":13},"fnMap":{"1":{"name":"Queue","line":3,"loc":{"start":{"line":3,"column":0},"end":{"line":3,"column":24}}},"2":{"name":"(anonymous_2)","line":22,"loc":{"start":{"line":22,"column":24},"end":{"line":22,"column":41}}},"3":{"name":"(anonymous_3)","line":23,"loc":{"start":{"line":23,"column":28},"end":{"line":23,"column":39}}},"4":{"name":"(anonymous_4)","line":31,"loc":{"start":{"line":31,"column":7},"end":{"line":31,"column":18}}},"5":{"name":"(anonymous_5)","line":36,"loc":{"start":{"line":36,"column":23},"end":{"line":36,"column":34}}},"6":{"name":"(anonymous_6)","line":55,"loc":{"start":{"line":55,"column":25},"end":{"line":55,"column":38}}},"7":{"name":"done","line":62,"loc":{"start":{"line":62,"column":0},"end":{"line":62,"column":16}}}},"statementMap":{"1":{"start":{"line":3,"column":0},"end":{"line":14,"column":1}},"2":{"start":{"line":4,"column":2},"end":{"line":6,"column":3}},"3":{"start":{"line":5,"column":4},"end":{"line":5,"column":30}},"4":{"start":{"line":8,"column":2},"end":{"line":8,"column":26}},"5":{"start":{"line":9,"column":2},"end":{"line":9,"column":53}},"6":{"start":{"line":10,"column":2},"end":{"line":10,"column":19}},"7":{"start":{"line":11,"column":2},"end":{"line":11,"column":17}},"8":{"start":{"line":12,"column":2},"end":{"line":12,"column":16}},"9":{"start":{"line":13,"column":2},"end":{"line":13,"column":31}},"10":{"start":{"line":16,"column":0},"end":{"line":20,"column":2}},"11":{"start":{"line":22,"column":0},"end":{"line":28,"column":3}},"12":{"start":{"line":23,"column":2},"end":{"line":27,"column":4}},"13":{"start":{"line":24,"column":4},"end":{"line":24,"column":75}},"14":{"start":{"line":25,"column":4},"end":{"line":25,"column":16}},"15":{"start":{"line":26,"column":4},"end":{"line":26,"column":24}},"16":{"start":{"line":30,"column":0},"end":{"line":34,"column":3}},"17":{"start":{"line":32,"column":4},"end":{"line":32,"column":43}},"18":{"start":{"line":36,"column":0},"end":{"line":53,"column":2}},"19":{"start":{"line":37,"column":2},"end":{"line":39,"column":3}},"20":{"start":{"line":38,"column":4},"end":{"line":38,"column":11}},"21":{"start":{"line":40,"column":2},"end":{"line":45,"column":3}},"22":{"start":{"line":41,"column":4},"end":{"line":41,"column":32}},"23":{"start":{"line":42,"column":4},"end":{"line":42,"column":19}},"24":{"start":{"line":43,"column":4},"end":{"line":43,"column":20}},"25":{"start":{"line":44,"column":4},"end":{"line":44,"column":16}},"26":{"start":{"line":47,"column":2},"end":{"line":52,"column":3}},"27":{"start":{"line":48,"column":4},"end":{"line":51,"column":5}},"28":{"start":{"line":49,"column":6},"end":{"line":49,"column":30}},"29":{"start":{"line":50,"column":6},"end":{"line":50,"column":27}},"30":{"start":{"line":55,"column":0},"end":{"line":60,"column":2}},"31":{"start":{"line":56,"column":2},"end":{"line":59,"column":3}},"32":{"start":{"line":57,"column":4},"end":{"line":57,"column":22}},"33":{"start":{"line":58,"column":4},"end":{"line":58,"column":16}},"34":{"start":{"line":62,"column":0},"end":{"line":65,"column":1}},"35":{"start":{"line":63,"column":2},"end":{"line":63,"column":17}},"36":{"start":{"line":64,"column":2},"end":{"line":64,"column":14}},"37":{"start":{"line":67,"column":0},"end":{"line":67,"column":23}}},"branchMap":{"1":{"line":4,"type":"if","locations":[{"start":{"line":4,"column":2},"end":{"line":4,"column":2}},{"start":{"line":4,"column":2},"end":{"line":4,"column":2}}]},"2":{"line":8,"type":"binary-expr","locations":[{"start":{"line":8,"column":12},"end":{"line":8,"column":19}},{"start":{"line":8,"column":23},"end":{"line":8,"column":25}}]},"3":{"line":9,"type":"binary-expr","locations":[{"start":{"line":9,"column":21},"end":{"line":9,"column":40}},{"start":{"line":9,"column":44},"end":{"line":9,"column":52}}]},"4":{"line":37,"type":"if","locations":[{"start":{"line":37,"column":2},"end":{"line":37,"column":2}},{"start":{"line":37,"column":2},"end":{"line":37,"column":2}}]},"5":{"line":40,"type":"if","locations":[{"start":{"line":40,"column":2},"end":{"line":40,"column":2}},{"start":{"line":40,"column":2},"end":{"line":40,"column":2}}]},"6":{"line":47,"type":"if","locations":[{"start":{"line":47,"column":2},"end":{"line":47,"column":2}},{"start":{"line":47,"column":2},"end":{"line":47,"column":2}}]},"7":{"line":56,"type":"if","locations":[{"start":{"line":56,"column":2},"end":{"line":56,"column":2}},{"start":{"line":56,"column":2},"end":{"line":56,"column":2}}]}}}} \ No newline at end of file diff --git a/express-server/node_modules/async-limiter/coverage/lcov-report/async-throttle/index.html b/express-server/node_modules/async-limiter/coverage/lcov-report/async-throttle/index.html new file mode 100644 index 00000000..198882b4 --- /dev/null +++ b/express-server/node_modules/async-limiter/coverage/lcov-report/async-throttle/index.html @@ -0,0 +1,73 @@ + + + + Code coverage report for async-throttle/ + + + + + + +
+

Code coverage report for async-throttle/

+

+ Statements: 100% (37 / 37)      + Branches: 92.86% (13 / 14)      + Functions: 100% (7 / 7)      + Lines: 100% (37 / 37)      + Ignored: none      +

+
All files » async-throttle/
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
index.js100%(37 / 37)92.86%(13 / 14)100%(7 / 7)100%(37 / 37)
+
+
+ + + + + + diff --git a/express-server/node_modules/async-limiter/coverage/lcov-report/async-throttle/index.js.html b/express-server/node_modules/async-limiter/coverage/lcov-report/async-throttle/index.js.html new file mode 100644 index 00000000..adc030fd --- /dev/null +++ b/express-server/node_modules/async-limiter/coverage/lcov-report/async-throttle/index.js.html @@ -0,0 +1,246 @@ + + + + Code coverage report for async-throttle/index.js + + + + + + +
+

Code coverage report for async-throttle/index.js

+

+ Statements: 100% (37 / 37)      + Branches: 92.86% (13 / 14)      + Functions: 100% (7 / 7)      + Lines: 100% (37 / 37)      + Ignored: none      +

+
All files » async-throttle/ » index.js
+
+
+

+
+
1 +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 +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 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68  +  +1 +7 +1 +  +  +6 +6 +6 +6 +6 +6 +  +  +1 +  +  +  +  +  +1 +3 +13 +13 +13 +  +  +  +1 +  +19 +  +  +  +1 +45 +6 +  +39 +13 +13 +13 +13 +  +  +39 +18 +6 +6 +  +  +  +  +1 +6 +6 +6 +  +  +  +1 +13 +13 +  +  +1 + 
'use strict';
+ 
+function Queue(options) {
+  if (!(this instanceof Queue)) {
+    return new Queue(options);
+  }
+ 
+  options = options || {};
+  this.concurrency = options.concurrency || Infinity;
+  this.pending = 0;
+  this.jobs = [];
+  this.cbs = [];
+  this._done = done.bind(this);
+}
+ 
+var arrayAddMethods = [
+  'push',
+  'unshift',
+  'splice'
+];
+ 
+arrayAddMethods.forEach(function(method) {
+  Queue.prototype[method] = function() {
+    var methodResult = Array.prototype[method].apply(this.jobs, arguments);
+    this._run();
+    return methodResult;
+  };
+});
+ 
+Object.defineProperty(Queue.prototype, 'length', {
+  get: function() {
+    return this.pending + this.jobs.length;
+  }
+});
+ 
+Queue.prototype._run = function() {
+  if (this.pending === this.concurrency) {
+    return;
+  }
+  if (this.jobs.length) {
+    var job = this.jobs.shift();
+    this.pending++;
+    job(this._done);
+    this._run();
+  }
+ 
+  if (this.pending === 0) {
+    while (this.cbs.length !== 0) {
+      var cb = this.cbs.pop();
+      process.nextTick(cb);
+    }
+  }
+};
+ 
+Queue.prototype.onDone = function(cb) {
+  Eif (typeof cb === 'function') {
+    this.cbs.push(cb);
+    this._run();
+  }
+};
+ 
+function done() {
+  this.pending--;
+  this._run();
+}
+ 
+module.exports = Queue;
+ 
+ +
+ + + + + + diff --git a/express-server/node_modules/async-limiter/coverage/lcov-report/base.css b/express-server/node_modules/async-limiter/coverage/lcov-report/base.css new file mode 100644 index 00000000..a6a2f328 --- /dev/null +++ b/express-server/node_modules/async-limiter/coverage/lcov-report/base.css @@ -0,0 +1,182 @@ +body, html { + margin:0; padding: 0; +} +body { + font-family: Helvetica Neue, Helvetica,Arial; + font-size: 10pt; +} +div.header, div.footer { + background: #eee; + padding: 1em; +} +div.header { + z-index: 100; + position: fixed; + top: 0; + border-bottom: 1px solid #666; + width: 100%; +} +div.footer { + border-top: 1px solid #666; +} +div.body { + margin-top: 10em; +} +div.meta { + font-size: 90%; + text-align: center; +} +h1, h2, h3 { + font-weight: normal; +} +h1 { + font-size: 12pt; +} +h2 { + font-size: 10pt; +} +pre { + font-family: Consolas, Menlo, Monaco, monospace; + margin: 0; + padding: 0; + line-height: 1.3; + font-size: 14px; + -moz-tab-size: 2; + -o-tab-size: 2; + tab-size: 2; +} + +div.path { font-size: 110%; } +div.path a:link, div.path a:visited { color: #000; } +table.coverage { border-collapse: collapse; margin:0; padding: 0 } + +table.coverage td { + margin: 0; + padding: 0; + color: #111; + vertical-align: top; +} +table.coverage td.line-count { + width: 50px; + text-align: right; + padding-right: 5px; +} +table.coverage td.line-coverage { + color: #777 !important; + text-align: right; + border-left: 1px solid #666; + border-right: 1px solid #666; +} + +table.coverage td.text { +} + +table.coverage td span.cline-any { + display: inline-block; + padding: 0 5px; + width: 40px; +} +table.coverage td span.cline-neutral { + background: #eee; +} +table.coverage td span.cline-yes { + background: #b5d592; + color: #999; +} +table.coverage td span.cline-no { + background: #fc8c84; +} + +.cstat-yes { color: #111; } +.cstat-no { background: #fc8c84; color: #111; } +.fstat-no { background: #ffc520; color: #111 !important; } +.cbranch-no { background: yellow !important; color: #111; } + +.cstat-skip { background: #ddd; color: #111; } +.fstat-skip { background: #ddd; color: #111 !important; } +.cbranch-skip { background: #ddd !important; color: #111; } + +.missing-if-branch { + display: inline-block; + margin-right: 10px; + position: relative; + padding: 0 4px; + background: black; + color: yellow; +} + +.skip-if-branch { + display: none; + margin-right: 10px; + position: relative; + padding: 0 4px; + background: #ccc; + color: white; +} + +.missing-if-branch .typ, .skip-if-branch .typ { + color: inherit !important; +} + +.entity, .metric { font-weight: bold; } +.metric { display: inline-block; border: 1px solid #333; padding: 0.3em; background: white; } +.metric small { font-size: 80%; font-weight: normal; color: #666; } + +div.coverage-summary table { border-collapse: collapse; margin: 3em; font-size: 110%; } +div.coverage-summary td, div.coverage-summary table th { margin: 0; padding: 0.25em 1em; border-top: 1px solid #666; border-bottom: 1px solid #666; } +div.coverage-summary th { text-align: left; border: 1px solid #666; background: #eee; font-weight: normal; } +div.coverage-summary th.file { border-right: none !important; } +div.coverage-summary th.pic { border-left: none !important; text-align: right; } +div.coverage-summary th.pct { border-right: none !important; } +div.coverage-summary th.abs { border-left: none !important; text-align: right; } +div.coverage-summary td.pct { text-align: right; border-left: 1px solid #666; } +div.coverage-summary td.abs { text-align: right; font-size: 90%; color: #444; border-right: 1px solid #666; } +div.coverage-summary td.file { border-left: 1px solid #666; white-space: nowrap; } +div.coverage-summary td.pic { min-width: 120px !important; } +div.coverage-summary a:link { text-decoration: none; color: #000; } +div.coverage-summary a:visited { text-decoration: none; color: #777; } +div.coverage-summary a:hover { text-decoration: underline; } +div.coverage-summary tfoot td { border-top: 1px solid #666; } + +div.coverage-summary .sorter { + height: 10px; + width: 7px; + display: inline-block; + margin-left: 0.5em; + background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; +} +div.coverage-summary .sorted .sorter { + background-position: 0 -20px; +} +div.coverage-summary .sorted-desc .sorter { + background-position: 0 -10px; +} + +.high { background: #b5d592 !important; } +.medium { background: #ffe87c !important; } +.low { background: #fc8c84 !important; } + +span.cover-fill, span.cover-empty { + display:inline-block; + border:1px solid #444; + background: white; + height: 12px; +} +span.cover-fill { + background: #ccc; + border-right: 1px solid #444; +} +span.cover-empty { + background: white; + border-left: none; +} +span.cover-full { + border-right: none !important; +} +pre.prettyprint { + border: none !important; + padding: 0 !important; + margin: 0 !important; +} +.com { color: #999 !important; } +.ignore-none { color: #999; font-weight: normal; } diff --git a/express-server/node_modules/async-limiter/coverage/lcov-report/index.html b/express-server/node_modules/async-limiter/coverage/lcov-report/index.html new file mode 100644 index 00000000..782a1cff --- /dev/null +++ b/express-server/node_modules/async-limiter/coverage/lcov-report/index.html @@ -0,0 +1,73 @@ + + + + Code coverage report for All files + + + + + + +
+

Code coverage report for All files

+

+ Statements: 100% (37 / 37)      + Branches: 92.86% (13 / 14)      + Functions: 100% (7 / 7)      + Lines: 100% (37 / 37)      + Ignored: none      +

+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FileStatementsBranchesFunctionsLines
async-throttle/100%(37 / 37)92.86%(13 / 14)100%(7 / 7)100%(37 / 37)
+
+
+ + + + + + diff --git a/express-server/node_modules/async-limiter/coverage/lcov-report/prettify.css b/express-server/node_modules/async-limiter/coverage/lcov-report/prettify.css new file mode 100644 index 00000000..b317a7cd --- /dev/null +++ b/express-server/node_modules/async-limiter/coverage/lcov-report/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/express-server/node_modules/async-limiter/coverage/lcov-report/prettify.js b/express-server/node_modules/async-limiter/coverage/lcov-report/prettify.js new file mode 100644 index 00000000..ef51e038 --- /dev/null +++ b/express-server/node_modules/async-limiter/coverage/lcov-report/prettify.js @@ -0,0 +1 @@ +window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/express-server/node_modules/async-limiter/coverage/lcov-report/sort-arrow-sprite.png b/express-server/node_modules/async-limiter/coverage/lcov-report/sort-arrow-sprite.png new file mode 100644 index 0000000000000000000000000000000000000000..03f704a609c6fd0dbfdac63466a7d7c958b5cbf3 GIT binary patch literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^>_9Bd!3HEZxJ@+%Qj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS>Jii$m5978H@?Fn+^JD|Y9yzj{W`447Gxa{7*dM7nnnD-Lb z6^}Hx2)'; + } + } + return cols; + } + // attaches a data attribute to every tr element with an object + // of data values keyed by column name + function loadRowData(tableRow) { + var tableCols = tableRow.querySelectorAll('td'), + colNode, + col, + data = {}, + i, + val; + for (i = 0; i < tableCols.length; i += 1) { + colNode = tableCols[i]; + col = cols[i]; + val = colNode.getAttribute('data-value'); + if (col.type === 'number') { + val = Number(val); + } + data[col.key] = val; + } + return data; + } + // loads all row data + function loadData() { + var rows = getTableBody().querySelectorAll('tr'), + i; + + for (i = 0; i < rows.length; i += 1) { + rows[i].data = loadRowData(rows[i]); + } + } + // sorts the table using the data for the ith column + function sortByIndex(index, desc) { + var key = cols[index].key, + sorter = function (a, b) { + a = a.data[key]; + b = b.data[key]; + return a < b ? -1 : a > b ? 1 : 0; + }, + finalSorter = sorter, + tableBody = document.querySelector('.coverage-summary tbody'), + rowNodes = tableBody.querySelectorAll('tr'), + rows = [], + i; + + if (desc) { + finalSorter = function (a, b) { + return -1 * sorter(a, b); + }; + } + + for (i = 0; i < rowNodes.length; i += 1) { + rows.push(rowNodes[i]); + tableBody.removeChild(rowNodes[i]); + } + + rows.sort(finalSorter); + + for (i = 0; i < rows.length; i += 1) { + tableBody.appendChild(rows[i]); + } + } + // removes sort indicators for current column being sorted + function removeSortIndicators() { + var col = getNthColumn(currentSort.index), + cls = col.className; + + cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); + col.className = cls; + } + // adds sort indicators for current column being sorted + function addSortIndicators() { + getNthColumn(currentSort.index).className += currentSort.desc ? ' sorted-desc' : ' sorted'; + } + // adds event listeners for all sorter widgets + function enableUI() { + var i, + el, + ithSorter = function ithSorter(i) { + var col = cols[i]; + + return function () { + var desc = col.defaultDescSort; + + if (currentSort.index === i) { + desc = !currentSort.desc; + } + sortByIndex(i, desc); + removeSortIndicators(); + currentSort.index = i; + currentSort.desc = desc; + addSortIndicators(); + }; + }; + for (i =0 ; i < cols.length; i += 1) { + if (cols[i].sortable) { + el = getNthColumn(i).querySelector('.sorter'); + if (el.addEventListener) { + el.addEventListener('click', ithSorter(i)); + } else { + el.attachEvent('onclick', ithSorter(i)); + } + } + } + } + // adds sorting functionality to the UI + return function () { + if (!getTable()) { + return; + } + cols = loadColumns(); + loadData(cols); + addSortIndicators(); + enableUI(); + }; +})(); + +window.addEventListener('load', addSorting); diff --git a/express-server/node_modules/async-limiter/coverage/lcov.info b/express-server/node_modules/async-limiter/coverage/lcov.info new file mode 100644 index 00000000..fbf36aab --- /dev/null +++ b/express-server/node_modules/async-limiter/coverage/lcov.info @@ -0,0 +1,74 @@ +TN: +SF:/Users/samuelreed/git/forks/async-throttle/index.js +FN:3,Queue +FN:22,(anonymous_2) +FN:23,(anonymous_3) +FN:31,(anonymous_4) +FN:36,(anonymous_5) +FN:55,(anonymous_6) +FN:62,done +FNF:7 +FNH:7 +FNDA:7,Queue +FNDA:3,(anonymous_2) +FNDA:13,(anonymous_3) +FNDA:19,(anonymous_4) +FNDA:45,(anonymous_5) +FNDA:6,(anonymous_6) +FNDA:13,done +DA:3,1 +DA:4,7 +DA:5,1 +DA:8,6 +DA:9,6 +DA:10,6 +DA:11,6 +DA:12,6 +DA:13,6 +DA:16,1 +DA:22,1 +DA:23,3 +DA:24,13 +DA:25,13 +DA:26,13 +DA:30,1 +DA:32,19 +DA:36,1 +DA:37,45 +DA:38,6 +DA:40,39 +DA:41,13 +DA:42,13 +DA:43,13 +DA:44,13 +DA:47,39 +DA:48,18 +DA:49,6 +DA:50,6 +DA:55,1 +DA:56,6 +DA:57,6 +DA:58,6 +DA:62,1 +DA:63,13 +DA:64,13 +DA:67,1 +LF:37 +LH:37 +BRDA:4,1,0,1 +BRDA:4,1,1,6 +BRDA:8,2,0,6 +BRDA:8,2,1,5 +BRDA:9,3,0,6 +BRDA:9,3,1,5 +BRDA:37,4,0,6 +BRDA:37,4,1,39 +BRDA:40,5,0,13 +BRDA:40,5,1,26 +BRDA:47,6,0,18 +BRDA:47,6,1,21 +BRDA:56,7,0,6 +BRDA:56,7,1,0 +BRF:14 +BRH:13 +end_of_record diff --git a/express-server/node_modules/async-limiter/index.js b/express-server/node_modules/async-limiter/index.js new file mode 100644 index 00000000..c9bd2f97 --- /dev/null +++ b/express-server/node_modules/async-limiter/index.js @@ -0,0 +1,67 @@ +'use strict'; + +function Queue(options) { + if (!(this instanceof Queue)) { + return new Queue(options); + } + + options = options || {}; + this.concurrency = options.concurrency || Infinity; + this.pending = 0; + this.jobs = []; + this.cbs = []; + this._done = done.bind(this); +} + +var arrayAddMethods = [ + 'push', + 'unshift', + 'splice' +]; + +arrayAddMethods.forEach(function(method) { + Queue.prototype[method] = function() { + var methodResult = Array.prototype[method].apply(this.jobs, arguments); + this._run(); + return methodResult; + }; +}); + +Object.defineProperty(Queue.prototype, 'length', { + get: function() { + return this.pending + this.jobs.length; + } +}); + +Queue.prototype._run = function() { + if (this.pending === this.concurrency) { + return; + } + if (this.jobs.length) { + var job = this.jobs.shift(); + this.pending++; + job(this._done); + this._run(); + } + + if (this.pending === 0) { + while (this.cbs.length !== 0) { + var cb = this.cbs.pop(); + process.nextTick(cb); + } + } +}; + +Queue.prototype.onDone = function(cb) { + if (typeof cb === 'function') { + this.cbs.push(cb); + this._run(); + } +}; + +function done() { + this.pending--; + this._run(); +} + +module.exports = Queue; diff --git a/express-server/node_modules/async-limiter/package.json b/express-server/node_modules/async-limiter/package.json new file mode 100644 index 00000000..02b8467d --- /dev/null +++ b/express-server/node_modules/async-limiter/package.json @@ -0,0 +1,97 @@ +{ + "_args": [ + [ + "async-limiter@~1.0.0", + "/nodeapps/https-test/greenlock-express.js/node_modules/ws" + ] + ], + "_from": "async-limiter@>=1.0.0 <1.1.0", + "_id": "async-limiter@1.0.0", + "_inCache": true, + "_installable": true, + "_location": "/async-limiter", + "_nodeVersion": "8.4.0", + "_npmOperationalInternal": { + "host": "s3://npm-registry-packages", + "tmp": "tmp/async-limiter-1.0.0.tgz_1505149068503_0.15003100014291704" + }, + "_npmUser": { + "email": "samuel.trace.reed@gmail.com", + "name": "strml" + }, + "_npmVersion": "5.4.1", + "_phantomChildren": {}, + "_requested": { + "name": "async-limiter", + "raw": "async-limiter@~1.0.0", + "rawSpec": "~1.0.0", + "scope": null, + "spec": ">=1.0.0 <1.1.0", + "type": "range" + }, + "_requiredBy": [ + "/ws" + ], + "_resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "_shasum": "78faed8c3d074ab81f22b4e985d79e8738f720f8", + "_shrinkwrap": null, + "_spec": "async-limiter@~1.0.0", + "_where": "/nodeapps/https-test/greenlock-express.js/node_modules/ws", + "author": { + "name": "Samuel Reed" + }, + "bugs": { + "url": "https://github.com/strml/async-limiter/issues" + }, + "dependencies": {}, + "description": "asynchronous function queue with adjustable concurrency", + "devDependencies": { + "coveralls": "^2.11.2", + "eslint": "^4.6.1", + "eslint-plugin-mocha": "^4.11.0", + "intelli-espower-loader": "^1.0.1", + "istanbul": "^0.3.2", + "mocha": "^3.5.2", + "power-assert": "^1.4.4" + }, + "directories": {}, + "dist": { + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "shasum": "78faed8c3d074ab81f22b4e985d79e8738f720f8", + "tarball": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz" + }, + "gitHead": "02c8b498279dc7cc1ecc1c4f6fc9ca320c0ce39b", + "homepage": "https://github.com/strml/async-limiter#readme", + "keywords": [ + "async", + "asynchronous", + "concurrency", + "concurrent", + "job", + "limiter", + "task", + "throttle" + ], + "license": "MIT", + "maintainers": [ + { + "name": "strml", + "email": "samuel.trace.reed@gmail.com" + } + ], + "name": "async-limiter", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/strml/async-limiter.git" + }, + "scripts": { + "coverage": "istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | coveralls", + "example": "node example", + "lint": "eslint .", + "test": "mocha --R intelli-espower-loader test/", + "travis": "npm run lint && npm run coverage" + }, + "version": "1.0.0" +} diff --git a/express-server/node_modules/async-limiter/readme.md b/express-server/node_modules/async-limiter/readme.md new file mode 100644 index 00000000..dcf4932f --- /dev/null +++ b/express-server/node_modules/async-limiter/readme.md @@ -0,0 +1,132 @@ +# Async-Limiter + +A module for limiting concurrent asynchronous actions in flight. Forked from [queue](https://github.com/jessetane/queue). + +[![npm](http://img.shields.io/npm/v/async-limiter.svg?style=flat-square)](http://www.npmjs.org/async-limiter) +[![tests](https://img.shields.io/travis/STRML/async-limiter.svg?style=flat-square&branch=master)](https://travis-ci.org/STRML/async-limiter) +[![coverage](https://img.shields.io/coveralls/STRML/async-limiter.svg?style=flat-square&branch=master)](https://coveralls.io/r/STRML/async-limiter) + +This module exports a class `Limiter` that implements some of the `Array` API. +Pass async functions (ones that accept a callback or return a promise) to an instance's additive array methods. + +## Motivation + +Certain functions, like `zlib`, have [undesirable behavior](https://github.com/nodejs/node/issues/8871#issuecomment-250915913) when +run at infinite concurrency. + +In this case, it is actually faster, and takes far less memory, to limit concurrency. + +This module should do the absolute minimum work necessary to queue up functions. PRs are welcome that would +make this module faster or lighter, but new functionality is not desired. + +Style should confirm to nodejs/node style. + +## Example + +``` javascript +var Limiter = require('async-limiter') + +var t = new Limiter({concurrency: 2}); +var results = [] + +// add jobs using the familiar Array API +t.push(function (cb) { + results.push('two') + cb() +}) + +t.push( + function (cb) { + results.push('four') + cb() + }, + function (cb) { + results.push('five') + cb() + } +) + +t.unshift(function (cb) { + results.push('one') + cb() +}) + +t.splice(2, 0, function (cb) { + results.push('three') + cb() +}) + +// Jobs run automatically. If you want a callback when all are done, +// call 'onDone()'. +t.onDone(function () { + console.log('all done:', results) +}) +``` + +## Zlib Example + +```js +const zlib = require('zlib'); +const Limiter = require('async-limiter'); + +const message = {some: "data"}; +const payload = new Buffer(JSON.stringify(message)); + +// Try with different concurrency values to see how this actually +// slows significantly with higher concurrency! +// +// 5: 1398.607ms +// 10: 1375.668ms +// Infinity: 4423.300ms +// +const t = new Limiter({concurrency: 5}); +function deflate(payload, cb) { + t.push(function(done) { + zlib.deflate(payload, function(err, buffer) { + done(); + cb(err, buffer); + }); + }); +} + +console.time('deflate'); +for(let i = 0; i < 30000; ++i) { + deflate(payload, function (err, buffer) {}); +} +q.onDone(function() { + console.timeEnd('deflate'); +}); +``` + +## Install + +`npm install async-limiter` + +## Test + +`npm test` + +## API + +### `var t = new Limiter([opts])` +Constructor. `opts` may contain inital values for: +* `q.concurrency` + +## Instance methods + +### `q.onDone(fn)` +`fn` will be called once and only once, when the queue is empty. + +## Instance methods mixed in from `Array` +Mozilla has docs on how these methods work [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array). +### `q.push(element1, ..., elementN)` +### `q.unshift(element1, ..., elementN)` +### `q.splice(index , howMany[, element1[, ...[, elementN]]])` + +## Properties +### `q.concurrency` +Max number of jobs the queue should process concurrently, defaults to `Infinity`. + +### `q.length` +Jobs pending + jobs to process (readonly). + diff --git a/express-server/node_modules/batch/.npmignore b/express-server/node_modules/batch/.npmignore new file mode 100644 index 00000000..f1250e58 --- /dev/null +++ b/express-server/node_modules/batch/.npmignore @@ -0,0 +1,4 @@ +support +test +examples +*.sock diff --git a/express-server/node_modules/batch/History.md b/express-server/node_modules/batch/History.md new file mode 100644 index 00000000..f7e9b76f --- /dev/null +++ b/express-server/node_modules/batch/History.md @@ -0,0 +1,93 @@ +0.6.1 / 2017-05-16 +================== + + * fix `process.nextTick` detection in Node.js + +0.6.0 / 2017-03-25 +================== + + * always invoke end callback asynchronously + * fix compatibility with component v1 + * fix license field + +0.5.3 / 2015-10-01 +================== + + * fix for browserify + +0.5.2 / 2014-12-22 +================== + + * add brower field + * add license to package.json + +0.5.1 / 2014-06-19 +================== + + * add repository field to readme (exciting) + +0.5.0 / 2013-07-29 +================== + + * add `.throws(true)` to opt-in to responding with an array of error objects + * make `new` optional + +0.4.0 / 2013-06-05 +================== + + * add catching of immediate callback errors + +0.3.2 / 2013-03-15 +================== + + * remove Emitter call in constructor + +0.3.1 / 2013-03-13 +================== + + * add Emitter() mixin for client. Closes #8 + +0.3.0 / 2013-03-13 +================== + + * add component.json + * add result example + * add .concurrency support + * add concurrency example + * add parallel example + +0.2.1 / 2012-11-08 +================== + + * add .start, .end, and .duration properties + * change dependencies to devDependencies + +0.2.0 / 2012-10-04 +================== + + * add progress events. Closes #5 (__BREAKING CHANGE__) + +0.1.1 / 2012-07-03 +================== + + * change "complete" event to "progress" + +0.1.0 / 2012-07-03 +================== + + * add Emitter inheritance and emit "complete" [burcu] + +0.0.3 / 2012-06-02 +================== + + * Callback results should be in the order of the queued functions. + +0.0.2 / 2012-02-12 +================== + + * any node + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/express-server/node_modules/batch/LICENSE b/express-server/node_modules/batch/LICENSE new file mode 100644 index 00000000..b7409302 --- /dev/null +++ b/express-server/node_modules/batch/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2013 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. diff --git a/express-server/node_modules/batch/Makefile b/express-server/node_modules/batch/Makefile new file mode 100644 index 00000000..634e3721 --- /dev/null +++ b/express-server/node_modules/batch/Makefile @@ -0,0 +1,6 @@ + +test: + @./node_modules/.bin/mocha \ + --require should + +.PHONY: test \ No newline at end of file diff --git a/express-server/node_modules/batch/Readme.md b/express-server/node_modules/batch/Readme.md new file mode 100644 index 00000000..c2b4d3d0 --- /dev/null +++ b/express-server/node_modules/batch/Readme.md @@ -0,0 +1,53 @@ + +# batch + + Simple async batch with concurrency control and progress reporting. + +## Installation + +``` +$ npm install batch +``` + +## API + +```js +var Batch = require('batch') + , batch = new Batch; + +batch.concurrency(4); + +ids.forEach(function(id){ + batch.push(function(done){ + User.get(id, done); + }); +}); + +batch.on('progress', function(e){ + +}); + +batch.end(function(err, users){ + +}); +``` + +### Progress events + + Contain the "job" index, response value, duration information, and completion data. + +``` +{ index: 1, + value: 'bar', + pending: 2, + total: 3, + complete: 2, + percent: 66, + start: Thu Oct 04 2012 12:25:53 GMT-0700 (PDT), + end: Thu Oct 04 2012 12:25:53 GMT-0700 (PDT), + duration: 0 } +``` + +## License + +[MIT](LICENSE) diff --git a/express-server/node_modules/batch/component.json b/express-server/node_modules/batch/component.json new file mode 100644 index 00000000..2715596c --- /dev/null +++ b/express-server/node_modules/batch/component.json @@ -0,0 +1,14 @@ +{ + "name": "batch", + "repo": "visionmedia/batch", + "description": "Async task batching", + "version": "0.6.1", + "keywords": ["batch", "async", "utility", "concurrency", "concurrent"], + "dependencies": { + "component/emitter": "*" + }, + "development": {}, + "scripts": [ + "index.js" + ] +} diff --git a/express-server/node_modules/batch/index.js b/express-server/node_modules/batch/index.js new file mode 100644 index 00000000..5b402550 --- /dev/null +++ b/express-server/node_modules/batch/index.js @@ -0,0 +1,173 @@ +/** + * Module dependencies. + */ + +try { + var EventEmitter = require('events').EventEmitter; + if (!EventEmitter) throw new Error(); +} catch (err) { + var Emitter = require('emitter'); +} + +/** + * Defer. + */ + +var defer = typeof process !== 'undefined' && process && typeof process.nextTick === 'function' + ? process.nextTick + : function(fn){ setTimeout(fn); }; + +/** + * Noop. + */ + +function noop(){} + +/** + * Expose `Batch`. + */ + +module.exports = Batch; + +/** + * Create a new Batch. + */ + +function Batch() { + if (!(this instanceof Batch)) return new Batch; + this.fns = []; + this.concurrency(Infinity); + this.throws(true); + for (var i = 0, len = arguments.length; i < len; ++i) { + this.push(arguments[i]); + } +} + +/** + * Inherit from `EventEmitter.prototype`. + */ + +if (EventEmitter) { + Batch.prototype.__proto__ = EventEmitter.prototype; +} else { + Emitter(Batch.prototype); +} + +/** + * Set concurrency to `n`. + * + * @param {Number} n + * @return {Batch} + * @api public + */ + +Batch.prototype.concurrency = function(n){ + this.n = n; + return this; +}; + +/** + * Queue a function. + * + * @param {Function} fn + * @return {Batch} + * @api public + */ + +Batch.prototype.push = function(fn){ + this.fns.push(fn); + return this; +}; + +/** + * Set wether Batch will or will not throw up. + * + * @param {Boolean} throws + * @return {Batch} + * @api public + */ +Batch.prototype.throws = function(throws) { + this.e = !!throws; + return this; +}; + +/** + * Execute all queued functions in parallel, + * executing `cb(err, results)`. + * + * @param {Function} cb + * @return {Batch} + * @api public + */ + +Batch.prototype.end = function(cb){ + var self = this + , total = this.fns.length + , pending = total + , results = [] + , errors = [] + , cb = cb || noop + , fns = this.fns + , max = this.n + , throws = this.e + , index = 0 + , done; + + // empty + if (!fns.length) return defer(function(){ + cb(null, results); + }); + + // process + function next() { + var i = index++; + var fn = fns[i]; + if (!fn) return; + var start = new Date; + + try { + fn(callback); + } catch (err) { + callback(err); + } + + function callback(err, res){ + if (done) return; + if (err && throws) return done = true, defer(function(){ + cb(err); + }); + var complete = total - pending + 1; + var end = new Date; + + results[i] = res; + errors[i] = err; + + self.emit('progress', { + index: i, + value: res, + error: err, + pending: pending, + total: total, + complete: complete, + percent: complete / total * 100 | 0, + start: start, + end: end, + duration: end - start + }); + + if (--pending) next(); + else defer(function(){ + if(!throws) cb(errors, results); + else cb(null, results); + }); + } + } + + // concurrency + for (var i = 0; i < fns.length; i++) { + if (i == max) break; + next(); + } + + return this; +}; diff --git a/express-server/node_modules/batch/package.json b/express-server/node_modules/batch/package.json new file mode 100644 index 00000000..10e37e91 --- /dev/null +++ b/express-server/node_modules/batch/package.json @@ -0,0 +1,84 @@ +{ + "_args": [ + [ + "batch@0.6.1", + "/nodeapps/https-test/greenlock-express.js/node_modules/serve-index" + ] + ], + "_from": "batch@0.6.1", + "_id": "batch@0.6.1", + "_inCache": true, + "_installable": true, + "_location": "/batch", + "_nodeVersion": "6.10.3", + "_npmOperationalInternal": { + "host": "packages-18-east.internal.npmjs.com", + "tmp": "tmp/batch-0.6.1.tgz_1494969108544_0.02703835256397724" + }, + "_npmUser": { + "email": "doug@somethingdoug.com", + "name": "dougwilson" + }, + "_npmVersion": "3.10.10", + "_phantomChildren": {}, + "_requested": { + "name": "batch", + "raw": "batch@0.6.1", + "rawSpec": "0.6.1", + "scope": null, + "spec": "0.6.1", + "type": "version" + }, + "_requiredBy": [ + "/serve-index" + ], + "_resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "_shasum": "dc34314f4e679318093fc760272525f94bf25c16", + "_shrinkwrap": null, + "_spec": "batch@0.6.1", + "_where": "/nodeapps/https-test/greenlock-express.js/node_modules/serve-index", + "author": { + "email": "tj@vision-media.ca", + "name": "TJ Holowaychuk" + }, + "browser": { + "emitter": "events" + }, + "bugs": { + "url": "https://github.com/visionmedia/batch/issues" + }, + "dependencies": {}, + "description": "Simple async batch with concurrency control and progress reporting.", + "devDependencies": { + "mocha": "*", + "should": "*" + }, + "directories": {}, + "dist": { + "shasum": "dc34314f4e679318093fc760272525f94bf25c16", + "tarball": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz" + }, + "gitHead": "577ea162b9be76e79d2fcc43c47ed573112e9892", + "homepage": "https://github.com/visionmedia/batch#readme", + "license": "MIT", + "main": "index", + "maintainers": [ + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "tjholowaychuk", + "email": "tj@vision-media.ca" + } + ], + "name": "batch", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/visionmedia/batch.git" + }, + "scripts": {}, + "version": "0.6.1" +} diff --git a/express-server/node_modules/bindings/README.md b/express-server/node_modules/bindings/README.md new file mode 100644 index 00000000..a1f0d225 --- /dev/null +++ b/express-server/node_modules/bindings/README.md @@ -0,0 +1,98 @@ +node-bindings +============= +### Helper module for loading your native module's .node file + +This is a helper module for authors of Node.js native addon modules. +It is basically the "swiss army knife" of `require()`ing your native module's +`.node` file. + +Throughout the course of Node's native addon history, addons have ended up being +compiled in a variety of different places, depending on which build tool and which +version of node was used. To make matters worse, now the _gyp_ build tool can +produce either a _Release_ or _Debug_ build, each being built into different +locations. + +This module checks _all_ the possible locations that a native addon would be built +at, and returns the first one that loads successfully. + + +Installation +------------ + +Install with `npm`: + +``` bash +$ npm install bindings +``` + +Or add it to the `"dependencies"` section of your _package.json_ file. + + +Example +------- + +`require()`ing the proper bindings file for the current node version, platform +and architecture is as simple as: + +``` js +var bindings = require('bindings')('binding.node') + +// Use your bindings defined in your C files +bindings.your_c_function() +``` + + +Nice Error Output +----------------- + +When the `.node` file could not be loaded, `node-bindings` throws an Error with +a nice error message telling you exactly what was tried. You can also check the +`err.tries` Array property. + +``` +Error: Could not load the bindings file. Tried: + → /Users/nrajlich/ref/build/binding.node + → /Users/nrajlich/ref/build/Debug/binding.node + → /Users/nrajlich/ref/build/Release/binding.node + → /Users/nrajlich/ref/out/Debug/binding.node + → /Users/nrajlich/ref/Debug/binding.node + → /Users/nrajlich/ref/out/Release/binding.node + → /Users/nrajlich/ref/Release/binding.node + → /Users/nrajlich/ref/build/default/binding.node + → /Users/nrajlich/ref/compiled/0.8.2/darwin/x64/binding.node + at bindings (/Users/nrajlich/ref/node_modules/bindings/bindings.js:84:13) + at Object. (/Users/nrajlich/ref/lib/ref.js:5:47) + at Module._compile (module.js:449:26) + at Object.Module._extensions..js (module.js:467:10) + at Module.load (module.js:356:32) + at Function.Module._load (module.js:312:12) + ... +``` + +The searching for the `.node` file will originate from the first directory in which has a `package.json` file is found. + +License +------- + +(The MIT License) + +Copyright (c) 2012 Nathan Rajlich <nathan@tootallnate.net> + +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/express-server/node_modules/bindings/bindings.js b/express-server/node_modules/bindings/bindings.js new file mode 100644 index 00000000..dec594f9 --- /dev/null +++ b/express-server/node_modules/bindings/bindings.js @@ -0,0 +1,174 @@ + +/** + * Module dependencies. + */ + +var fs = require('fs') + , path = require('path') + , join = path.join + , dirname = path.dirname + , exists = ((fs.accessSync && function (path) { try { fs.accessSync(path); } catch (e) { return false; } return true; }) + || fs.existsSync || path.existsSync) + , defaults = { + arrow: process.env.NODE_BINDINGS_ARROW || ' → ' + , compiled: process.env.NODE_BINDINGS_COMPILED_DIR || 'compiled' + , platform: process.platform + , arch: process.arch + , version: process.versions.node + , bindings: 'bindings.node' + , try: [ + // node-gyp's linked version in the "build" dir + [ 'module_root', 'build', 'bindings' ] + // node-waf and gyp_addon (a.k.a node-gyp) + , [ 'module_root', 'build', 'Debug', 'bindings' ] + , [ 'module_root', 'build', 'Release', 'bindings' ] + // Debug files, for development (legacy behavior, remove for node v0.9) + , [ 'module_root', 'out', 'Debug', 'bindings' ] + , [ 'module_root', 'Debug', 'bindings' ] + // Release files, but manually compiled (legacy behavior, remove for node v0.9) + , [ 'module_root', 'out', 'Release', 'bindings' ] + , [ 'module_root', 'Release', 'bindings' ] + // Legacy from node-waf, node <= 0.4.x + , [ 'module_root', 'build', 'default', 'bindings' ] + // Production "Release" buildtype binary (meh...) + , [ 'module_root', 'compiled', 'version', 'platform', 'arch', 'bindings' ] + ] + } + +/** + * The main `bindings()` function loads the compiled bindings for a given module. + * It uses V8's Error API to determine the parent filename that this function is + * being invoked from, which is then used to find the root directory. + */ + +function bindings (opts) { + + // Argument surgery + if (typeof opts == 'string') { + opts = { bindings: opts } + } else if (!opts) { + opts = {} + } + + // maps `defaults` onto `opts` object + Object.keys(defaults).map(function(i) { + if (!(i in opts)) opts[i] = defaults[i]; + }); + + // Get the module root + if (!opts.module_root) { + opts.module_root = exports.getRoot(exports.getFileName()) + } + + // Ensure the given bindings name ends with .node + if (path.extname(opts.bindings) != '.node') { + opts.bindings += '.node' + } + + // https://github.com/webpack/webpack/issues/4175#issuecomment-342931035 + var requireFunc = typeof __webpack_require__ === 'function' ? __non_webpack_require__ : require + + var tries = [] + , i = 0 + , l = opts.try.length + , n + , b + , err + + for (; i=1.3.0 <2.0.0", + "_hasShrinkwrap": false, + "_id": "bindings@1.3.1", + "_inCache": true, + "_installable": true, + "_location": "/bindings", + "_nodeVersion": "10.13.0", + "_npmOperationalInternal": { + "host": "s3://npm-registry-packages", + "tmp": "tmp/bindings_1.3.1_1543265368475_0.5592200215369445" + }, + "_npmUser": { + "email": "nathan@tootallnate.net", + "name": "tootallnate" + }, + "_npmVersion": "6.4.1", + "_phantomChildren": {}, + "_requested": { + "name": "bindings", + "raw": "bindings@^1.3.0", + "rawSpec": "^1.3.0", + "scope": null, + "spec": ">=1.3.0 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/ursa-optional" + ], + "_resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.1.tgz", + "_shasum": "21fc7c6d67c18516ec5aaa2815b145ff77b26ea5", + "_shrinkwrap": null, + "_spec": "bindings@^1.3.0", + "_where": "/nodeapps/https-test/greenlock-express.js/node_modules/ursa-optional", + "author": { + "email": "nathan@tootallnate.net", + "name": "Nathan Rajlich", + "url": "http://tootallnate.net" + }, + "bugs": { + "url": "https://github.com/TooTallNate/node-bindings/issues" + }, + "dependencies": {}, + "description": "Helper module for loading your native module's .node file", + "devDependencies": {}, + "directories": {}, + "dist": { + "fileCount": 3, + "integrity": "sha512-i47mqjF9UbjxJhxGf+pZ6kSxrnI3wBLlnGI2ArWJ4r0VrvDS7ZYXkprq/pLaBWYq4GM0r4zdHY+NNRqEMU7uew==", + "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb/FxZCRA9TVsSAnZWagAAhVQP/jQl2mQD1vWSzK5/xAf5\njtcv2Vhixd7Tp8a/ZzjU1e/hKWa7GtlGgKd1c5T3LcPuBJYOXDIH8VRtWo3U\n9xxQl9+1E2JuA8p9Yps/HwKGbOSTPtYft8i6w0S9RgpTXpwM5duDOso9bPLC\nqUmP6zaD71FOx6g5f9vlw8NL9pHTANLcHEqV2m8YWDSEXRTC8dUw3qnYtvAd\nfGy9lpw/JQaC4QGny5xuy4u+cfuP6WIyWusM72jQKWIr1tdGrGPWDApLqH5j\nEVuC10tt5bkN4qzW59BZ74YRr42SEraC/UZt6d4rzHc8N2rGoNiCg0zIBNgb\nYTbiF9aIFq9gnU0Zn97idQZ33Gk5Ici4IS4/JGwQhjJ1u2zj0qnVV7uE7BIm\nJazUdbPvKbYGRZqOXEJYe8lhkvuwzud94bLDi5k0whTX3cdVm1iP8gHMXn7R\nB1D4yZZRUP8/e/m/2jDX+FNi3IenmX+vAQGPi6myTeaedbP8q/PN3XPBdRZ+\nSQ+Oie89Lj5v4m1cMErNWl9n9E71me8d8a3Yn9Tu+2o1w/FGvVmXEuCjD3qL\nVCyoeXYSsewCsknRoUr+ST8v0UnmL6g1crbUtBxaFNwcubjvddb45FkEK2r1\n5RR/yg6ZU0sZ+2KR/XLI26mG/sLP/y9tKA7XEMOj406h8mNi3N1fFcKbHmU/\nYaFQ\r\n=z9PJ\r\n-----END PGP SIGNATURE-----\r\n", + "shasum": "21fc7c6d67c18516ec5aaa2815b145ff77b26ea5", + "tarball": "https://registry.npmjs.org/bindings/-/bindings-1.3.1.tgz", + "unpackedSize": 9107 + }, + "gitHead": "81ba74973e97ff2e42aa4bbae8de057ae62e9387", + "homepage": "https://github.com/TooTallNate/node-bindings", + "keywords": [ + "addon", + "bindings", + "c", + "c++", + "gyp", + "native", + "waf" + ], + "license": "MIT", + "main": "./bindings.js", + "maintainers": [ + { + "name": "tootallnate", + "email": "nathan@tootallnate.net" + } + ], + "name": "bindings", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/TooTallNate/node-bindings.git" + }, + "version": "1.3.1" +} diff --git a/express-server/node_modules/bluebird/LICENSE b/express-server/node_modules/bluebird/LICENSE new file mode 100644 index 00000000..b24e6350 --- /dev/null +++ b/express-server/node_modules/bluebird/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013-2018 Petka Antonov + +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/express-server/node_modules/bluebird/README.md b/express-server/node_modules/bluebird/README.md new file mode 100644 index 00000000..0eb5b74a --- /dev/null +++ b/express-server/node_modules/bluebird/README.md @@ -0,0 +1,57 @@ + + Promises/A+ logo + + + +[![Build Status](https://travis-ci.org/petkaantonov/bluebird.svg?branch=master)](https://travis-ci.org/petkaantonov/bluebird) +[![coverage-98%](https://img.shields.io/badge/coverage-98%25-brightgreen.svg?style=flat)](http://petkaantonov.github.io/bluebird/coverage/debug/index.html) + +**Got a question?** Join us on [stackoverflow](http://stackoverflow.com/questions/tagged/bluebird), the [mailing list](https://groups.google.com/forum/#!forum/bluebird-js) or chat on [IRC](https://webchat.freenode.net/?channels=#promises) + +# Introduction + +Bluebird is a fully featured promise library with focus on innovative features and performance + +See the [**bluebird website**](http://bluebirdjs.com/docs/getting-started.html) for further documentation, references and instructions. See the [**API reference**](http://bluebirdjs.com/docs/api-reference.html) here. + +For bluebird 2.x documentation and files, see the [2.x tree](https://github.com/petkaantonov/bluebird/tree/2.x). + +### Note + +Promises in Node.js 10 are significantly faster than before. Bluebird still includes a lot of features like cancellation, iteration methods and warnings that native promises don't. If you are using Bluebird for performance rather than for those - please consider giving native promises a shot and running the benchmarks yourself. + +# Questions and issues + +The [github issue tracker](https://github.com/petkaantonov/bluebird/issues) is **_only_** for bug reports and feature requests. Anything else, such as questions for help in using the library, should be posted in [StackOverflow](http://stackoverflow.com/questions/tagged/bluebird) under tags `promise` and `bluebird`. + + + +## Thanks + +Thanks to BrowserStack for providing us with a free account which lets us support old browsers like IE8. + +# License + +The MIT License (MIT) + +Copyright (c) 2013-2017 Petka Antonov + +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/express-server/node_modules/bluebird/changelog.md b/express-server/node_modules/bluebird/changelog.md new file mode 100644 index 00000000..73b2eb6c --- /dev/null +++ b/express-server/node_modules/bluebird/changelog.md @@ -0,0 +1 @@ +[http://bluebirdjs.com/docs/changelog.html](http://bluebirdjs.com/docs/changelog.html) diff --git a/express-server/node_modules/bluebird/js/browser/bluebird.core.js b/express-server/node_modules/bluebird/js/browser/bluebird.core.js new file mode 100644 index 00000000..626406f5 --- /dev/null +++ b/express-server/node_modules/bluebird/js/browser/bluebird.core.js @@ -0,0 +1,3805 @@ +/* @preserve + * The MIT License (MIT) + * + * Copyright (c) 2013-2018 Petka Antonov + * + * 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. + * + */ +/** + * bluebird build version 3.5.3 + * Features enabled: core + * Features disabled: race, call_get, generators, map, nodeify, promisify, props, reduce, settle, some, using, timers, filter, any, each +*/ +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Promise=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof _dereq_=="function"&&_dereq_;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof _dereq_=="function"&&_dereq_;for(var o=0;o 0) { + _drainQueueStep(queue); + } +} + +function _drainQueueStep(queue) { + var fn = queue.shift(); + if (typeof fn !== "function") { + fn._settlePromises(); + } else { + var receiver = queue.shift(); + var arg = queue.shift(); + fn.call(receiver, arg); + } +} + +Async.prototype._drainQueues = function () { + _drainQueue(this._normalQueue); + this._reset(); + this._haveDrainedQueues = true; + _drainQueue(this._lateQueue); +}; + +Async.prototype._queueTick = function () { + if (!this._isTickUsed) { + this._isTickUsed = true; + this._schedule(this.drainQueues); + } +}; + +Async.prototype._reset = function () { + this._isTickUsed = false; +}; + +module.exports = Async; +module.exports.firstLineError = firstLineError; + +},{"./queue":17,"./schedule":18,"./util":21}],2:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, INTERNAL, tryConvertToPromise, debug) { +var calledBind = false; +var rejectThis = function(_, e) { + this._reject(e); +}; + +var targetRejected = function(e, context) { + context.promiseRejectionQueued = true; + context.bindingPromise._then(rejectThis, rejectThis, null, this, e); +}; + +var bindingResolved = function(thisArg, context) { + if (((this._bitField & 50397184) === 0)) { + this._resolveCallback(context.target); + } +}; + +var bindingRejected = function(e, context) { + if (!context.promiseRejectionQueued) this._reject(e); +}; + +Promise.prototype.bind = function (thisArg) { + if (!calledBind) { + calledBind = true; + Promise.prototype._propagateFrom = debug.propagateFromFunction(); + Promise.prototype._boundValue = debug.boundValueFunction(); + } + var maybePromise = tryConvertToPromise(thisArg); + var ret = new Promise(INTERNAL); + ret._propagateFrom(this, 1); + var target = this._target(); + ret._setBoundTo(maybePromise); + if (maybePromise instanceof Promise) { + var context = { + promiseRejectionQueued: false, + promise: ret, + target: target, + bindingPromise: maybePromise + }; + target._then(INTERNAL, targetRejected, undefined, ret, context); + maybePromise._then( + bindingResolved, bindingRejected, undefined, ret, context); + ret._setOnCancel(maybePromise); + } else { + ret._resolveCallback(target); + } + return ret; +}; + +Promise.prototype._setBoundTo = function (obj) { + if (obj !== undefined) { + this._bitField = this._bitField | 2097152; + this._boundTo = obj; + } else { + this._bitField = this._bitField & (~2097152); + } +}; + +Promise.prototype._isBound = function () { + return (this._bitField & 2097152) === 2097152; +}; + +Promise.bind = function (thisArg, value) { + return Promise.resolve(value).bind(thisArg); +}; +}; + +},{}],3:[function(_dereq_,module,exports){ +"use strict"; +var old; +if (typeof Promise !== "undefined") old = Promise; +function noConflict() { + try { if (Promise === bluebird) Promise = old; } + catch (e) {} + return bluebird; +} +var bluebird = _dereq_("./promise")(); +bluebird.noConflict = noConflict; +module.exports = bluebird; + +},{"./promise":15}],4:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, PromiseArray, apiRejection, debug) { +var util = _dereq_("./util"); +var tryCatch = util.tryCatch; +var errorObj = util.errorObj; +var async = Promise._async; + +Promise.prototype["break"] = Promise.prototype.cancel = function() { + if (!debug.cancellation()) return this._warn("cancellation is disabled"); + + var promise = this; + var child = promise; + while (promise._isCancellable()) { + if (!promise._cancelBy(child)) { + if (child._isFollowing()) { + child._followee().cancel(); + } else { + child._cancelBranched(); + } + break; + } + + var parent = promise._cancellationParent; + if (parent == null || !parent._isCancellable()) { + if (promise._isFollowing()) { + promise._followee().cancel(); + } else { + promise._cancelBranched(); + } + break; + } else { + if (promise._isFollowing()) promise._followee().cancel(); + promise._setWillBeCancelled(); + child = promise; + promise = parent; + } + } +}; + +Promise.prototype._branchHasCancelled = function() { + this._branchesRemainingToCancel--; +}; + +Promise.prototype._enoughBranchesHaveCancelled = function() { + return this._branchesRemainingToCancel === undefined || + this._branchesRemainingToCancel <= 0; +}; + +Promise.prototype._cancelBy = function(canceller) { + if (canceller === this) { + this._branchesRemainingToCancel = 0; + this._invokeOnCancel(); + return true; + } else { + this._branchHasCancelled(); + if (this._enoughBranchesHaveCancelled()) { + this._invokeOnCancel(); + return true; + } + } + return false; +}; + +Promise.prototype._cancelBranched = function() { + if (this._enoughBranchesHaveCancelled()) { + this._cancel(); + } +}; + +Promise.prototype._cancel = function() { + if (!this._isCancellable()) return; + this._setCancelled(); + async.invoke(this._cancelPromises, this, undefined); +}; + +Promise.prototype._cancelPromises = function() { + if (this._length() > 0) this._settlePromises(); +}; + +Promise.prototype._unsetOnCancel = function() { + this._onCancelField = undefined; +}; + +Promise.prototype._isCancellable = function() { + return this.isPending() && !this._isCancelled(); +}; + +Promise.prototype.isCancellable = function() { + return this.isPending() && !this.isCancelled(); +}; + +Promise.prototype._doInvokeOnCancel = function(onCancelCallback, internalOnly) { + if (util.isArray(onCancelCallback)) { + for (var i = 0; i < onCancelCallback.length; ++i) { + this._doInvokeOnCancel(onCancelCallback[i], internalOnly); + } + } else if (onCancelCallback !== undefined) { + if (typeof onCancelCallback === "function") { + if (!internalOnly) { + var e = tryCatch(onCancelCallback).call(this._boundValue()); + if (e === errorObj) { + this._attachExtraTrace(e.e); + async.throwLater(e.e); + } + } + } else { + onCancelCallback._resultCancelled(this); + } + } +}; + +Promise.prototype._invokeOnCancel = function() { + var onCancelCallback = this._onCancel(); + this._unsetOnCancel(); + async.invoke(this._doInvokeOnCancel, this, onCancelCallback); +}; + +Promise.prototype._invokeInternalOnCancel = function() { + if (this._isCancellable()) { + this._doInvokeOnCancel(this._onCancel(), true); + this._unsetOnCancel(); + } +}; + +Promise.prototype._resultCancelled = function() { + this.cancel(); +}; + +}; + +},{"./util":21}],5:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(NEXT_FILTER) { +var util = _dereq_("./util"); +var getKeys = _dereq_("./es5").keys; +var tryCatch = util.tryCatch; +var errorObj = util.errorObj; + +function catchFilter(instances, cb, promise) { + return function(e) { + var boundTo = promise._boundValue(); + predicateLoop: for (var i = 0; i < instances.length; ++i) { + var item = instances[i]; + + if (item === Error || + (item != null && item.prototype instanceof Error)) { + if (e instanceof item) { + return tryCatch(cb).call(boundTo, e); + } + } else if (typeof item === "function") { + var matchesPredicate = tryCatch(item).call(boundTo, e); + if (matchesPredicate === errorObj) { + return matchesPredicate; + } else if (matchesPredicate) { + return tryCatch(cb).call(boundTo, e); + } + } else if (util.isObject(e)) { + var keys = getKeys(item); + for (var j = 0; j < keys.length; ++j) { + var key = keys[j]; + if (item[key] != e[key]) { + continue predicateLoop; + } + } + return tryCatch(cb).call(boundTo, e); + } + } + return NEXT_FILTER; + }; +} + +return catchFilter; +}; + +},{"./es5":10,"./util":21}],6:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise) { +var longStackTraces = false; +var contextStack = []; + +Promise.prototype._promiseCreated = function() {}; +Promise.prototype._pushContext = function() {}; +Promise.prototype._popContext = function() {return null;}; +Promise._peekContext = Promise.prototype._peekContext = function() {}; + +function Context() { + this._trace = new Context.CapturedTrace(peekContext()); +} +Context.prototype._pushContext = function () { + if (this._trace !== undefined) { + this._trace._promiseCreated = null; + contextStack.push(this._trace); + } +}; + +Context.prototype._popContext = function () { + if (this._trace !== undefined) { + var trace = contextStack.pop(); + var ret = trace._promiseCreated; + trace._promiseCreated = null; + return ret; + } + return null; +}; + +function createContext() { + if (longStackTraces) return new Context(); +} + +function peekContext() { + var lastIndex = contextStack.length - 1; + if (lastIndex >= 0) { + return contextStack[lastIndex]; + } + return undefined; +} +Context.CapturedTrace = null; +Context.create = createContext; +Context.deactivateLongStackTraces = function() {}; +Context.activateLongStackTraces = function() { + var Promise_pushContext = Promise.prototype._pushContext; + var Promise_popContext = Promise.prototype._popContext; + var Promise_PeekContext = Promise._peekContext; + var Promise_peekContext = Promise.prototype._peekContext; + var Promise_promiseCreated = Promise.prototype._promiseCreated; + Context.deactivateLongStackTraces = function() { + Promise.prototype._pushContext = Promise_pushContext; + Promise.prototype._popContext = Promise_popContext; + Promise._peekContext = Promise_PeekContext; + Promise.prototype._peekContext = Promise_peekContext; + Promise.prototype._promiseCreated = Promise_promiseCreated; + longStackTraces = false; + }; + longStackTraces = true; + Promise.prototype._pushContext = Context.prototype._pushContext; + Promise.prototype._popContext = Context.prototype._popContext; + Promise._peekContext = Promise.prototype._peekContext = peekContext; + Promise.prototype._promiseCreated = function() { + var ctx = this._peekContext(); + if (ctx && ctx._promiseCreated == null) ctx._promiseCreated = this; + }; +}; +return Context; +}; + +},{}],7:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, Context) { +var getDomain = Promise._getDomain; +var async = Promise._async; +var Warning = _dereq_("./errors").Warning; +var util = _dereq_("./util"); +var es5 = _dereq_("./es5"); +var canAttachTrace = util.canAttachTrace; +var unhandledRejectionHandled; +var possiblyUnhandledRejection; +var bluebirdFramePattern = + /[\\\/]bluebird[\\\/]js[\\\/](release|debug|instrumented)/; +var nodeFramePattern = /\((?:timers\.js):\d+:\d+\)/; +var parseLinePattern = /[\/<\(](.+?):(\d+):(\d+)\)?\s*$/; +var stackFramePattern = null; +var formatStack = null; +var indentStackFrames = false; +var printWarning; +var debugging = !!(util.env("BLUEBIRD_DEBUG") != 0 && + (true || + util.env("BLUEBIRD_DEBUG") || + util.env("NODE_ENV") === "development")); + +var warnings = !!(util.env("BLUEBIRD_WARNINGS") != 0 && + (debugging || util.env("BLUEBIRD_WARNINGS"))); + +var longStackTraces = !!(util.env("BLUEBIRD_LONG_STACK_TRACES") != 0 && + (debugging || util.env("BLUEBIRD_LONG_STACK_TRACES"))); + +var wForgottenReturn = util.env("BLUEBIRD_W_FORGOTTEN_RETURN") != 0 && + (warnings || !!util.env("BLUEBIRD_W_FORGOTTEN_RETURN")); + +Promise.prototype.suppressUnhandledRejections = function() { + var target = this._target(); + target._bitField = ((target._bitField & (~1048576)) | + 524288); +}; + +Promise.prototype._ensurePossibleRejectionHandled = function () { + if ((this._bitField & 524288) !== 0) return; + this._setRejectionIsUnhandled(); + var self = this; + setTimeout(function() { + self._notifyUnhandledRejection(); + }, 1); +}; + +Promise.prototype._notifyUnhandledRejectionIsHandled = function () { + fireRejectionEvent("rejectionHandled", + unhandledRejectionHandled, undefined, this); +}; + +Promise.prototype._setReturnedNonUndefined = function() { + this._bitField = this._bitField | 268435456; +}; + +Promise.prototype._returnedNonUndefined = function() { + return (this._bitField & 268435456) !== 0; +}; + +Promise.prototype._notifyUnhandledRejection = function () { + if (this._isRejectionUnhandled()) { + var reason = this._settledValue(); + this._setUnhandledRejectionIsNotified(); + fireRejectionEvent("unhandledRejection", + possiblyUnhandledRejection, reason, this); + } +}; + +Promise.prototype._setUnhandledRejectionIsNotified = function () { + this._bitField = this._bitField | 262144; +}; + +Promise.prototype._unsetUnhandledRejectionIsNotified = function () { + this._bitField = this._bitField & (~262144); +}; + +Promise.prototype._isUnhandledRejectionNotified = function () { + return (this._bitField & 262144) > 0; +}; + +Promise.prototype._setRejectionIsUnhandled = function () { + this._bitField = this._bitField | 1048576; +}; + +Promise.prototype._unsetRejectionIsUnhandled = function () { + this._bitField = this._bitField & (~1048576); + if (this._isUnhandledRejectionNotified()) { + this._unsetUnhandledRejectionIsNotified(); + this._notifyUnhandledRejectionIsHandled(); + } +}; + +Promise.prototype._isRejectionUnhandled = function () { + return (this._bitField & 1048576) > 0; +}; + +Promise.prototype._warn = function(message, shouldUseOwnTrace, promise) { + return warn(message, shouldUseOwnTrace, promise || this); +}; + +Promise.onPossiblyUnhandledRejection = function (fn) { + var domain = getDomain(); + possiblyUnhandledRejection = + typeof fn === "function" ? (domain === null ? + fn : util.domainBind(domain, fn)) + : undefined; +}; + +Promise.onUnhandledRejectionHandled = function (fn) { + var domain = getDomain(); + unhandledRejectionHandled = + typeof fn === "function" ? (domain === null ? + fn : util.domainBind(domain, fn)) + : undefined; +}; + +var disableLongStackTraces = function() {}; +Promise.longStackTraces = function () { + if (async.haveItemsQueued() && !config.longStackTraces) { + throw new Error("cannot enable long stack traces after promises have been created\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + if (!config.longStackTraces && longStackTracesIsSupported()) { + var Promise_captureStackTrace = Promise.prototype._captureStackTrace; + var Promise_attachExtraTrace = Promise.prototype._attachExtraTrace; + var Promise_dereferenceTrace = Promise.prototype._dereferenceTrace; + config.longStackTraces = true; + disableLongStackTraces = function() { + if (async.haveItemsQueued() && !config.longStackTraces) { + throw new Error("cannot enable long stack traces after promises have been created\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + Promise.prototype._captureStackTrace = Promise_captureStackTrace; + Promise.prototype._attachExtraTrace = Promise_attachExtraTrace; + Promise.prototype._dereferenceTrace = Promise_dereferenceTrace; + Context.deactivateLongStackTraces(); + async.enableTrampoline(); + config.longStackTraces = false; + }; + Promise.prototype._captureStackTrace = longStackTracesCaptureStackTrace; + Promise.prototype._attachExtraTrace = longStackTracesAttachExtraTrace; + Promise.prototype._dereferenceTrace = longStackTracesDereferenceTrace; + Context.activateLongStackTraces(); + async.disableTrampolineIfNecessary(); + } +}; + +Promise.hasLongStackTraces = function () { + return config.longStackTraces && longStackTracesIsSupported(); +}; + +var fireDomEvent = (function() { + try { + if (typeof CustomEvent === "function") { + var event = new CustomEvent("CustomEvent"); + util.global.dispatchEvent(event); + return function(name, event) { + var eventData = { + detail: event, + cancelable: true + }; + es5.defineProperty( + eventData, "promise", {value: event.promise}); + es5.defineProperty(eventData, "reason", {value: event.reason}); + var domEvent = new CustomEvent(name.toLowerCase(), eventData); + return !util.global.dispatchEvent(domEvent); + }; + } else if (typeof Event === "function") { + var event = new Event("CustomEvent"); + util.global.dispatchEvent(event); + return function(name, event) { + var domEvent = new Event(name.toLowerCase(), { + cancelable: true + }); + domEvent.detail = event; + es5.defineProperty(domEvent, "promise", {value: event.promise}); + es5.defineProperty(domEvent, "reason", {value: event.reason}); + return !util.global.dispatchEvent(domEvent); + }; + } else { + var event = document.createEvent("CustomEvent"); + event.initCustomEvent("testingtheevent", false, true, {}); + util.global.dispatchEvent(event); + return function(name, event) { + var domEvent = document.createEvent("CustomEvent"); + domEvent.initCustomEvent(name.toLowerCase(), false, true, + event); + return !util.global.dispatchEvent(domEvent); + }; + } + } catch (e) {} + return function() { + return false; + }; +})(); + +var fireGlobalEvent = (function() { + if (util.isNode) { + return function() { + return process.emit.apply(process, arguments); + }; + } else { + if (!util.global) { + return function() { + return false; + }; + } + return function(name) { + var methodName = "on" + name.toLowerCase(); + var method = util.global[methodName]; + if (!method) return false; + method.apply(util.global, [].slice.call(arguments, 1)); + return true; + }; + } +})(); + +function generatePromiseLifecycleEventObject(name, promise) { + return {promise: promise}; +} + +var eventToObjectGenerator = { + promiseCreated: generatePromiseLifecycleEventObject, + promiseFulfilled: generatePromiseLifecycleEventObject, + promiseRejected: generatePromiseLifecycleEventObject, + promiseResolved: generatePromiseLifecycleEventObject, + promiseCancelled: generatePromiseLifecycleEventObject, + promiseChained: function(name, promise, child) { + return {promise: promise, child: child}; + }, + warning: function(name, warning) { + return {warning: warning}; + }, + unhandledRejection: function (name, reason, promise) { + return {reason: reason, promise: promise}; + }, + rejectionHandled: generatePromiseLifecycleEventObject +}; + +var activeFireEvent = function (name) { + var globalEventFired = false; + try { + globalEventFired = fireGlobalEvent.apply(null, arguments); + } catch (e) { + async.throwLater(e); + globalEventFired = true; + } + + var domEventFired = false; + try { + domEventFired = fireDomEvent(name, + eventToObjectGenerator[name].apply(null, arguments)); + } catch (e) { + async.throwLater(e); + domEventFired = true; + } + + return domEventFired || globalEventFired; +}; + +Promise.config = function(opts) { + opts = Object(opts); + if ("longStackTraces" in opts) { + if (opts.longStackTraces) { + Promise.longStackTraces(); + } else if (!opts.longStackTraces && Promise.hasLongStackTraces()) { + disableLongStackTraces(); + } + } + if ("warnings" in opts) { + var warningsOption = opts.warnings; + config.warnings = !!warningsOption; + wForgottenReturn = config.warnings; + + if (util.isObject(warningsOption)) { + if ("wForgottenReturn" in warningsOption) { + wForgottenReturn = !!warningsOption.wForgottenReturn; + } + } + } + if ("cancellation" in opts && opts.cancellation && !config.cancellation) { + if (async.haveItemsQueued()) { + throw new Error( + "cannot enable cancellation after promises are in use"); + } + Promise.prototype._clearCancellationData = + cancellationClearCancellationData; + Promise.prototype._propagateFrom = cancellationPropagateFrom; + Promise.prototype._onCancel = cancellationOnCancel; + Promise.prototype._setOnCancel = cancellationSetOnCancel; + Promise.prototype._attachCancellationCallback = + cancellationAttachCancellationCallback; + Promise.prototype._execute = cancellationExecute; + propagateFromFunction = cancellationPropagateFrom; + config.cancellation = true; + } + if ("monitoring" in opts) { + if (opts.monitoring && !config.monitoring) { + config.monitoring = true; + Promise.prototype._fireEvent = activeFireEvent; + } else if (!opts.monitoring && config.monitoring) { + config.monitoring = false; + Promise.prototype._fireEvent = defaultFireEvent; + } + } + return Promise; +}; + +function defaultFireEvent() { return false; } + +Promise.prototype._fireEvent = defaultFireEvent; +Promise.prototype._execute = function(executor, resolve, reject) { + try { + executor(resolve, reject); + } catch (e) { + return e; + } +}; +Promise.prototype._onCancel = function () {}; +Promise.prototype._setOnCancel = function (handler) { ; }; +Promise.prototype._attachCancellationCallback = function(onCancel) { + ; +}; +Promise.prototype._captureStackTrace = function () {}; +Promise.prototype._attachExtraTrace = function () {}; +Promise.prototype._dereferenceTrace = function () {}; +Promise.prototype._clearCancellationData = function() {}; +Promise.prototype._propagateFrom = function (parent, flags) { + ; + ; +}; + +function cancellationExecute(executor, resolve, reject) { + var promise = this; + try { + executor(resolve, reject, function(onCancel) { + if (typeof onCancel !== "function") { + throw new TypeError("onCancel must be a function, got: " + + util.toString(onCancel)); + } + promise._attachCancellationCallback(onCancel); + }); + } catch (e) { + return e; + } +} + +function cancellationAttachCancellationCallback(onCancel) { + if (!this._isCancellable()) return this; + + var previousOnCancel = this._onCancel(); + if (previousOnCancel !== undefined) { + if (util.isArray(previousOnCancel)) { + previousOnCancel.push(onCancel); + } else { + this._setOnCancel([previousOnCancel, onCancel]); + } + } else { + this._setOnCancel(onCancel); + } +} + +function cancellationOnCancel() { + return this._onCancelField; +} + +function cancellationSetOnCancel(onCancel) { + this._onCancelField = onCancel; +} + +function cancellationClearCancellationData() { + this._cancellationParent = undefined; + this._onCancelField = undefined; +} + +function cancellationPropagateFrom(parent, flags) { + if ((flags & 1) !== 0) { + this._cancellationParent = parent; + var branchesRemainingToCancel = parent._branchesRemainingToCancel; + if (branchesRemainingToCancel === undefined) { + branchesRemainingToCancel = 0; + } + parent._branchesRemainingToCancel = branchesRemainingToCancel + 1; + } + if ((flags & 2) !== 0 && parent._isBound()) { + this._setBoundTo(parent._boundTo); + } +} + +function bindingPropagateFrom(parent, flags) { + if ((flags & 2) !== 0 && parent._isBound()) { + this._setBoundTo(parent._boundTo); + } +} +var propagateFromFunction = bindingPropagateFrom; + +function boundValueFunction() { + var ret = this._boundTo; + if (ret !== undefined) { + if (ret instanceof Promise) { + if (ret.isFulfilled()) { + return ret.value(); + } else { + return undefined; + } + } + } + return ret; +} + +function longStackTracesCaptureStackTrace() { + this._trace = new CapturedTrace(this._peekContext()); +} + +function longStackTracesAttachExtraTrace(error, ignoreSelf) { + if (canAttachTrace(error)) { + var trace = this._trace; + if (trace !== undefined) { + if (ignoreSelf) trace = trace._parent; + } + if (trace !== undefined) { + trace.attachExtraTrace(error); + } else if (!error.__stackCleaned__) { + var parsed = parseStackAndMessage(error); + util.notEnumerableProp(error, "stack", + parsed.message + "\n" + parsed.stack.join("\n")); + util.notEnumerableProp(error, "__stackCleaned__", true); + } + } +} + +function longStackTracesDereferenceTrace() { + this._trace = undefined; +} + +function checkForgottenReturns(returnValue, promiseCreated, name, promise, + parent) { + if (returnValue === undefined && promiseCreated !== null && + wForgottenReturn) { + if (parent !== undefined && parent._returnedNonUndefined()) return; + if ((promise._bitField & 65535) === 0) return; + + if (name) name = name + " "; + var handlerLine = ""; + var creatorLine = ""; + if (promiseCreated._trace) { + var traceLines = promiseCreated._trace.stack.split("\n"); + var stack = cleanStack(traceLines); + for (var i = stack.length - 1; i >= 0; --i) { + var line = stack[i]; + if (!nodeFramePattern.test(line)) { + var lineMatches = line.match(parseLinePattern); + if (lineMatches) { + handlerLine = "at " + lineMatches[1] + + ":" + lineMatches[2] + ":" + lineMatches[3] + " "; + } + break; + } + } + + if (stack.length > 0) { + var firstUserLine = stack[0]; + for (var i = 0; i < traceLines.length; ++i) { + + if (traceLines[i] === firstUserLine) { + if (i > 0) { + creatorLine = "\n" + traceLines[i - 1]; + } + break; + } + } + + } + } + var msg = "a promise was created in a " + name + + "handler " + handlerLine + "but was not returned from it, " + + "see http://goo.gl/rRqMUw" + + creatorLine; + promise._warn(msg, true, promiseCreated); + } +} + +function deprecated(name, replacement) { + var message = name + + " is deprecated and will be removed in a future version."; + if (replacement) message += " Use " + replacement + " instead."; + return warn(message); +} + +function warn(message, shouldUseOwnTrace, promise) { + if (!config.warnings) return; + var warning = new Warning(message); + var ctx; + if (shouldUseOwnTrace) { + promise._attachExtraTrace(warning); + } else if (config.longStackTraces && (ctx = Promise._peekContext())) { + ctx.attachExtraTrace(warning); + } else { + var parsed = parseStackAndMessage(warning); + warning.stack = parsed.message + "\n" + parsed.stack.join("\n"); + } + + if (!activeFireEvent("warning", warning)) { + formatAndLogError(warning, "", true); + } +} + +function reconstructStack(message, stacks) { + for (var i = 0; i < stacks.length - 1; ++i) { + stacks[i].push("From previous event:"); + stacks[i] = stacks[i].join("\n"); + } + if (i < stacks.length) { + stacks[i] = stacks[i].join("\n"); + } + return message + "\n" + stacks.join("\n"); +} + +function removeDuplicateOrEmptyJumps(stacks) { + for (var i = 0; i < stacks.length; ++i) { + if (stacks[i].length === 0 || + ((i + 1 < stacks.length) && stacks[i][0] === stacks[i+1][0])) { + stacks.splice(i, 1); + i--; + } + } +} + +function removeCommonRoots(stacks) { + var current = stacks[0]; + for (var i = 1; i < stacks.length; ++i) { + var prev = stacks[i]; + var currentLastIndex = current.length - 1; + var currentLastLine = current[currentLastIndex]; + var commonRootMeetPoint = -1; + + for (var j = prev.length - 1; j >= 0; --j) { + if (prev[j] === currentLastLine) { + commonRootMeetPoint = j; + break; + } + } + + for (var j = commonRootMeetPoint; j >= 0; --j) { + var line = prev[j]; + if (current[currentLastIndex] === line) { + current.pop(); + currentLastIndex--; + } else { + break; + } + } + current = prev; + } +} + +function cleanStack(stack) { + var ret = []; + for (var i = 0; i < stack.length; ++i) { + var line = stack[i]; + var isTraceLine = " (No stack trace)" === line || + stackFramePattern.test(line); + var isInternalFrame = isTraceLine && shouldIgnore(line); + if (isTraceLine && !isInternalFrame) { + if (indentStackFrames && line.charAt(0) !== " ") { + line = " " + line; + } + ret.push(line); + } + } + return ret; +} + +function stackFramesAsArray(error) { + var stack = error.stack.replace(/\s+$/g, "").split("\n"); + for (var i = 0; i < stack.length; ++i) { + var line = stack[i]; + if (" (No stack trace)" === line || stackFramePattern.test(line)) { + break; + } + } + if (i > 0 && error.name != "SyntaxError") { + stack = stack.slice(i); + } + return stack; +} + +function parseStackAndMessage(error) { + var stack = error.stack; + var message = error.toString(); + stack = typeof stack === "string" && stack.length > 0 + ? stackFramesAsArray(error) : [" (No stack trace)"]; + return { + message: message, + stack: error.name == "SyntaxError" ? stack : cleanStack(stack) + }; +} + +function formatAndLogError(error, title, isSoft) { + if (typeof console !== "undefined") { + var message; + if (util.isObject(error)) { + var stack = error.stack; + message = title + formatStack(stack, error); + } else { + message = title + String(error); + } + if (typeof printWarning === "function") { + printWarning(message, isSoft); + } else if (typeof console.log === "function" || + typeof console.log === "object") { + console.log(message); + } + } +} + +function fireRejectionEvent(name, localHandler, reason, promise) { + var localEventFired = false; + try { + if (typeof localHandler === "function") { + localEventFired = true; + if (name === "rejectionHandled") { + localHandler(promise); + } else { + localHandler(reason, promise); + } + } + } catch (e) { + async.throwLater(e); + } + + if (name === "unhandledRejection") { + if (!activeFireEvent(name, reason, promise) && !localEventFired) { + formatAndLogError(reason, "Unhandled rejection "); + } + } else { + activeFireEvent(name, promise); + } +} + +function formatNonError(obj) { + var str; + if (typeof obj === "function") { + str = "[function " + + (obj.name || "anonymous") + + "]"; + } else { + str = obj && typeof obj.toString === "function" + ? obj.toString() : util.toString(obj); + var ruselessToString = /\[object [a-zA-Z0-9$_]+\]/; + if (ruselessToString.test(str)) { + try { + var newStr = JSON.stringify(obj); + str = newStr; + } + catch(e) { + + } + } + if (str.length === 0) { + str = "(empty array)"; + } + } + return ("(<" + snip(str) + ">, no stack trace)"); +} + +function snip(str) { + var maxChars = 41; + if (str.length < maxChars) { + return str; + } + return str.substr(0, maxChars - 3) + "..."; +} + +function longStackTracesIsSupported() { + return typeof captureStackTrace === "function"; +} + +var shouldIgnore = function() { return false; }; +var parseLineInfoRegex = /[\/<\(]([^:\/]+):(\d+):(?:\d+)\)?\s*$/; +function parseLineInfo(line) { + var matches = line.match(parseLineInfoRegex); + if (matches) { + return { + fileName: matches[1], + line: parseInt(matches[2], 10) + }; + } +} + +function setBounds(firstLineError, lastLineError) { + if (!longStackTracesIsSupported()) return; + var firstStackLines = firstLineError.stack.split("\n"); + var lastStackLines = lastLineError.stack.split("\n"); + var firstIndex = -1; + var lastIndex = -1; + var firstFileName; + var lastFileName; + for (var i = 0; i < firstStackLines.length; ++i) { + var result = parseLineInfo(firstStackLines[i]); + if (result) { + firstFileName = result.fileName; + firstIndex = result.line; + break; + } + } + for (var i = 0; i < lastStackLines.length; ++i) { + var result = parseLineInfo(lastStackLines[i]); + if (result) { + lastFileName = result.fileName; + lastIndex = result.line; + break; + } + } + if (firstIndex < 0 || lastIndex < 0 || !firstFileName || !lastFileName || + firstFileName !== lastFileName || firstIndex >= lastIndex) { + return; + } + + shouldIgnore = function(line) { + if (bluebirdFramePattern.test(line)) return true; + var info = parseLineInfo(line); + if (info) { + if (info.fileName === firstFileName && + (firstIndex <= info.line && info.line <= lastIndex)) { + return true; + } + } + return false; + }; +} + +function CapturedTrace(parent) { + this._parent = parent; + this._promisesCreated = 0; + var length = this._length = 1 + (parent === undefined ? 0 : parent._length); + captureStackTrace(this, CapturedTrace); + if (length > 32) this.uncycle(); +} +util.inherits(CapturedTrace, Error); +Context.CapturedTrace = CapturedTrace; + +CapturedTrace.prototype.uncycle = function() { + var length = this._length; + if (length < 2) return; + var nodes = []; + var stackToIndex = {}; + + for (var i = 0, node = this; node !== undefined; ++i) { + nodes.push(node); + node = node._parent; + } + length = this._length = i; + for (var i = length - 1; i >= 0; --i) { + var stack = nodes[i].stack; + if (stackToIndex[stack] === undefined) { + stackToIndex[stack] = i; + } + } + for (var i = 0; i < length; ++i) { + var currentStack = nodes[i].stack; + var index = stackToIndex[currentStack]; + if (index !== undefined && index !== i) { + if (index > 0) { + nodes[index - 1]._parent = undefined; + nodes[index - 1]._length = 1; + } + nodes[i]._parent = undefined; + nodes[i]._length = 1; + var cycleEdgeNode = i > 0 ? nodes[i - 1] : this; + + if (index < length - 1) { + cycleEdgeNode._parent = nodes[index + 1]; + cycleEdgeNode._parent.uncycle(); + cycleEdgeNode._length = + cycleEdgeNode._parent._length + 1; + } else { + cycleEdgeNode._parent = undefined; + cycleEdgeNode._length = 1; + } + var currentChildLength = cycleEdgeNode._length + 1; + for (var j = i - 2; j >= 0; --j) { + nodes[j]._length = currentChildLength; + currentChildLength++; + } + return; + } + } +}; + +CapturedTrace.prototype.attachExtraTrace = function(error) { + if (error.__stackCleaned__) return; + this.uncycle(); + var parsed = parseStackAndMessage(error); + var message = parsed.message; + var stacks = [parsed.stack]; + + var trace = this; + while (trace !== undefined) { + stacks.push(cleanStack(trace.stack.split("\n"))); + trace = trace._parent; + } + removeCommonRoots(stacks); + removeDuplicateOrEmptyJumps(stacks); + util.notEnumerableProp(error, "stack", reconstructStack(message, stacks)); + util.notEnumerableProp(error, "__stackCleaned__", true); +}; + +var captureStackTrace = (function stackDetection() { + var v8stackFramePattern = /^\s*at\s*/; + var v8stackFormatter = function(stack, error) { + if (typeof stack === "string") return stack; + + if (error.name !== undefined && + error.message !== undefined) { + return error.toString(); + } + return formatNonError(error); + }; + + if (typeof Error.stackTraceLimit === "number" && + typeof Error.captureStackTrace === "function") { + Error.stackTraceLimit += 6; + stackFramePattern = v8stackFramePattern; + formatStack = v8stackFormatter; + var captureStackTrace = Error.captureStackTrace; + + shouldIgnore = function(line) { + return bluebirdFramePattern.test(line); + }; + return function(receiver, ignoreUntil) { + Error.stackTraceLimit += 6; + captureStackTrace(receiver, ignoreUntil); + Error.stackTraceLimit -= 6; + }; + } + var err = new Error(); + + if (typeof err.stack === "string" && + err.stack.split("\n")[0].indexOf("stackDetection@") >= 0) { + stackFramePattern = /@/; + formatStack = v8stackFormatter; + indentStackFrames = true; + return function captureStackTrace(o) { + o.stack = new Error().stack; + }; + } + + var hasStackAfterThrow; + try { throw new Error(); } + catch(e) { + hasStackAfterThrow = ("stack" in e); + } + if (!("stack" in err) && hasStackAfterThrow && + typeof Error.stackTraceLimit === "number") { + stackFramePattern = v8stackFramePattern; + formatStack = v8stackFormatter; + return function captureStackTrace(o) { + Error.stackTraceLimit += 6; + try { throw new Error(); } + catch(e) { o.stack = e.stack; } + Error.stackTraceLimit -= 6; + }; + } + + formatStack = function(stack, error) { + if (typeof stack === "string") return stack; + + if ((typeof error === "object" || + typeof error === "function") && + error.name !== undefined && + error.message !== undefined) { + return error.toString(); + } + return formatNonError(error); + }; + + return null; + +})([]); + +if (typeof console !== "undefined" && typeof console.warn !== "undefined") { + printWarning = function (message) { + console.warn(message); + }; + if (util.isNode && process.stderr.isTTY) { + printWarning = function(message, isSoft) { + var color = isSoft ? "\u001b[33m" : "\u001b[31m"; + console.warn(color + message + "\u001b[0m\n"); + }; + } else if (!util.isNode && typeof (new Error().stack) === "string") { + printWarning = function(message, isSoft) { + console.warn("%c" + message, + isSoft ? "color: darkorange" : "color: red"); + }; + } +} + +var config = { + warnings: warnings, + longStackTraces: false, + cancellation: false, + monitoring: false +}; + +if (longStackTraces) Promise.longStackTraces(); + +return { + longStackTraces: function() { + return config.longStackTraces; + }, + warnings: function() { + return config.warnings; + }, + cancellation: function() { + return config.cancellation; + }, + monitoring: function() { + return config.monitoring; + }, + propagateFromFunction: function() { + return propagateFromFunction; + }, + boundValueFunction: function() { + return boundValueFunction; + }, + checkForgottenReturns: checkForgottenReturns, + setBounds: setBounds, + warn: warn, + deprecated: deprecated, + CapturedTrace: CapturedTrace, + fireDomEvent: fireDomEvent, + fireGlobalEvent: fireGlobalEvent +}; +}; + +},{"./errors":9,"./es5":10,"./util":21}],8:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise) { +function returner() { + return this.value; +} +function thrower() { + throw this.reason; +} + +Promise.prototype["return"] = +Promise.prototype.thenReturn = function (value) { + if (value instanceof Promise) value.suppressUnhandledRejections(); + return this._then( + returner, undefined, undefined, {value: value}, undefined); +}; + +Promise.prototype["throw"] = +Promise.prototype.thenThrow = function (reason) { + return this._then( + thrower, undefined, undefined, {reason: reason}, undefined); +}; + +Promise.prototype.catchThrow = function (reason) { + if (arguments.length <= 1) { + return this._then( + undefined, thrower, undefined, {reason: reason}, undefined); + } else { + var _reason = arguments[1]; + var handler = function() {throw _reason;}; + return this.caught(reason, handler); + } +}; + +Promise.prototype.catchReturn = function (value) { + if (arguments.length <= 1) { + if (value instanceof Promise) value.suppressUnhandledRejections(); + return this._then( + undefined, returner, undefined, {value: value}, undefined); + } else { + var _value = arguments[1]; + if (_value instanceof Promise) _value.suppressUnhandledRejections(); + var handler = function() {return _value;}; + return this.caught(value, handler); + } +}; +}; + +},{}],9:[function(_dereq_,module,exports){ +"use strict"; +var es5 = _dereq_("./es5"); +var Objectfreeze = es5.freeze; +var util = _dereq_("./util"); +var inherits = util.inherits; +var notEnumerableProp = util.notEnumerableProp; + +function subError(nameProperty, defaultMessage) { + function SubError(message) { + if (!(this instanceof SubError)) return new SubError(message); + notEnumerableProp(this, "message", + typeof message === "string" ? message : defaultMessage); + notEnumerableProp(this, "name", nameProperty); + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } else { + Error.call(this); + } + } + inherits(SubError, Error); + return SubError; +} + +var _TypeError, _RangeError; +var Warning = subError("Warning", "warning"); +var CancellationError = subError("CancellationError", "cancellation error"); +var TimeoutError = subError("TimeoutError", "timeout error"); +var AggregateError = subError("AggregateError", "aggregate error"); +try { + _TypeError = TypeError; + _RangeError = RangeError; +} catch(e) { + _TypeError = subError("TypeError", "type error"); + _RangeError = subError("RangeError", "range error"); +} + +var methods = ("join pop push shift unshift slice filter forEach some " + + "every map indexOf lastIndexOf reduce reduceRight sort reverse").split(" "); + +for (var i = 0; i < methods.length; ++i) { + if (typeof Array.prototype[methods[i]] === "function") { + AggregateError.prototype[methods[i]] = Array.prototype[methods[i]]; + } +} + +es5.defineProperty(AggregateError.prototype, "length", { + value: 0, + configurable: false, + writable: true, + enumerable: true +}); +AggregateError.prototype["isOperational"] = true; +var level = 0; +AggregateError.prototype.toString = function() { + var indent = Array(level * 4 + 1).join(" "); + var ret = "\n" + indent + "AggregateError of:" + "\n"; + level++; + indent = Array(level * 4 + 1).join(" "); + for (var i = 0; i < this.length; ++i) { + var str = this[i] === this ? "[Circular AggregateError]" : this[i] + ""; + var lines = str.split("\n"); + for (var j = 0; j < lines.length; ++j) { + lines[j] = indent + lines[j]; + } + str = lines.join("\n"); + ret += str + "\n"; + } + level--; + return ret; +}; + +function OperationalError(message) { + if (!(this instanceof OperationalError)) + return new OperationalError(message); + notEnumerableProp(this, "name", "OperationalError"); + notEnumerableProp(this, "message", message); + this.cause = message; + this["isOperational"] = true; + + if (message instanceof Error) { + notEnumerableProp(this, "message", message.message); + notEnumerableProp(this, "stack", message.stack); + } else if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + +} +inherits(OperationalError, Error); + +var errorTypes = Error["__BluebirdErrorTypes__"]; +if (!errorTypes) { + errorTypes = Objectfreeze({ + CancellationError: CancellationError, + TimeoutError: TimeoutError, + OperationalError: OperationalError, + RejectionError: OperationalError, + AggregateError: AggregateError + }); + es5.defineProperty(Error, "__BluebirdErrorTypes__", { + value: errorTypes, + writable: false, + enumerable: false, + configurable: false + }); +} + +module.exports = { + Error: Error, + TypeError: _TypeError, + RangeError: _RangeError, + CancellationError: errorTypes.CancellationError, + OperationalError: errorTypes.OperationalError, + TimeoutError: errorTypes.TimeoutError, + AggregateError: errorTypes.AggregateError, + Warning: Warning +}; + +},{"./es5":10,"./util":21}],10:[function(_dereq_,module,exports){ +var isES5 = (function(){ + "use strict"; + return this === undefined; +})(); + +if (isES5) { + module.exports = { + freeze: Object.freeze, + defineProperty: Object.defineProperty, + getDescriptor: Object.getOwnPropertyDescriptor, + keys: Object.keys, + names: Object.getOwnPropertyNames, + getPrototypeOf: Object.getPrototypeOf, + isArray: Array.isArray, + isES5: isES5, + propertyIsWritable: function(obj, prop) { + var descriptor = Object.getOwnPropertyDescriptor(obj, prop); + return !!(!descriptor || descriptor.writable || descriptor.set); + } + }; +} else { + var has = {}.hasOwnProperty; + var str = {}.toString; + var proto = {}.constructor.prototype; + + var ObjectKeys = function (o) { + var ret = []; + for (var key in o) { + if (has.call(o, key)) { + ret.push(key); + } + } + return ret; + }; + + var ObjectGetDescriptor = function(o, key) { + return {value: o[key]}; + }; + + var ObjectDefineProperty = function (o, key, desc) { + o[key] = desc.value; + return o; + }; + + var ObjectFreeze = function (obj) { + return obj; + }; + + var ObjectGetPrototypeOf = function (obj) { + try { + return Object(obj).constructor.prototype; + } + catch (e) { + return proto; + } + }; + + var ArrayIsArray = function (obj) { + try { + return str.call(obj) === "[object Array]"; + } + catch(e) { + return false; + } + }; + + module.exports = { + isArray: ArrayIsArray, + keys: ObjectKeys, + names: ObjectKeys, + defineProperty: ObjectDefineProperty, + getDescriptor: ObjectGetDescriptor, + freeze: ObjectFreeze, + getPrototypeOf: ObjectGetPrototypeOf, + isES5: isES5, + propertyIsWritable: function() { + return true; + } + }; +} + +},{}],11:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, tryConvertToPromise, NEXT_FILTER) { +var util = _dereq_("./util"); +var CancellationError = Promise.CancellationError; +var errorObj = util.errorObj; +var catchFilter = _dereq_("./catch_filter")(NEXT_FILTER); + +function PassThroughHandlerContext(promise, type, handler) { + this.promise = promise; + this.type = type; + this.handler = handler; + this.called = false; + this.cancelPromise = null; +} + +PassThroughHandlerContext.prototype.isFinallyHandler = function() { + return this.type === 0; +}; + +function FinallyHandlerCancelReaction(finallyHandler) { + this.finallyHandler = finallyHandler; +} + +FinallyHandlerCancelReaction.prototype._resultCancelled = function() { + checkCancel(this.finallyHandler); +}; + +function checkCancel(ctx, reason) { + if (ctx.cancelPromise != null) { + if (arguments.length > 1) { + ctx.cancelPromise._reject(reason); + } else { + ctx.cancelPromise._cancel(); + } + ctx.cancelPromise = null; + return true; + } + return false; +} + +function succeed() { + return finallyHandler.call(this, this.promise._target()._settledValue()); +} +function fail(reason) { + if (checkCancel(this, reason)) return; + errorObj.e = reason; + return errorObj; +} +function finallyHandler(reasonOrValue) { + var promise = this.promise; + var handler = this.handler; + + if (!this.called) { + this.called = true; + var ret = this.isFinallyHandler() + ? handler.call(promise._boundValue()) + : handler.call(promise._boundValue(), reasonOrValue); + if (ret === NEXT_FILTER) { + return ret; + } else if (ret !== undefined) { + promise._setReturnedNonUndefined(); + var maybePromise = tryConvertToPromise(ret, promise); + if (maybePromise instanceof Promise) { + if (this.cancelPromise != null) { + if (maybePromise._isCancelled()) { + var reason = + new CancellationError("late cancellation observer"); + promise._attachExtraTrace(reason); + errorObj.e = reason; + return errorObj; + } else if (maybePromise.isPending()) { + maybePromise._attachCancellationCallback( + new FinallyHandlerCancelReaction(this)); + } + } + return maybePromise._then( + succeed, fail, undefined, this, undefined); + } + } + } + + if (promise.isRejected()) { + checkCancel(this); + errorObj.e = reasonOrValue; + return errorObj; + } else { + checkCancel(this); + return reasonOrValue; + } +} + +Promise.prototype._passThrough = function(handler, type, success, fail) { + if (typeof handler !== "function") return this.then(); + return this._then(success, + fail, + undefined, + new PassThroughHandlerContext(this, type, handler), + undefined); +}; + +Promise.prototype.lastly = +Promise.prototype["finally"] = function (handler) { + return this._passThrough(handler, + 0, + finallyHandler, + finallyHandler); +}; + + +Promise.prototype.tap = function (handler) { + return this._passThrough(handler, 1, finallyHandler); +}; + +Promise.prototype.tapCatch = function (handlerOrPredicate) { + var len = arguments.length; + if(len === 1) { + return this._passThrough(handlerOrPredicate, + 1, + undefined, + finallyHandler); + } else { + var catchInstances = new Array(len - 1), + j = 0, i; + for (i = 0; i < len - 1; ++i) { + var item = arguments[i]; + if (util.isObject(item)) { + catchInstances[j++] = item; + } else { + return Promise.reject(new TypeError( + "tapCatch statement predicate: " + + "expecting an object but got " + util.classString(item) + )); + } + } + catchInstances.length = j; + var handler = arguments[i]; + return this._passThrough(catchFilter(catchInstances, handler, this), + 1, + undefined, + finallyHandler); + } + +}; + +return PassThroughHandlerContext; +}; + +},{"./catch_filter":5,"./util":21}],12:[function(_dereq_,module,exports){ +"use strict"; +module.exports = +function(Promise, PromiseArray, tryConvertToPromise, INTERNAL, async, + getDomain) { +var util = _dereq_("./util"); +var canEvaluate = util.canEvaluate; +var tryCatch = util.tryCatch; +var errorObj = util.errorObj; +var reject; + +if (!true) { +if (canEvaluate) { + var thenCallback = function(i) { + return new Function("value", "holder", " \n\ + 'use strict'; \n\ + holder.pIndex = value; \n\ + holder.checkFulfillment(this); \n\ + ".replace(/Index/g, i)); + }; + + var promiseSetter = function(i) { + return new Function("promise", "holder", " \n\ + 'use strict'; \n\ + holder.pIndex = promise; \n\ + ".replace(/Index/g, i)); + }; + + var generateHolderClass = function(total) { + var props = new Array(total); + for (var i = 0; i < props.length; ++i) { + props[i] = "this.p" + (i+1); + } + var assignment = props.join(" = ") + " = null;"; + var cancellationCode= "var promise;\n" + props.map(function(prop) { + return " \n\ + promise = " + prop + "; \n\ + if (promise instanceof Promise) { \n\ + promise.cancel(); \n\ + } \n\ + "; + }).join("\n"); + var passedArguments = props.join(", "); + var name = "Holder$" + total; + + + var code = "return function(tryCatch, errorObj, Promise, async) { \n\ + 'use strict'; \n\ + function [TheName](fn) { \n\ + [TheProperties] \n\ + this.fn = fn; \n\ + this.asyncNeeded = true; \n\ + this.now = 0; \n\ + } \n\ + \n\ + [TheName].prototype._callFunction = function(promise) { \n\ + promise._pushContext(); \n\ + var ret = tryCatch(this.fn)([ThePassedArguments]); \n\ + promise._popContext(); \n\ + if (ret === errorObj) { \n\ + promise._rejectCallback(ret.e, false); \n\ + } else { \n\ + promise._resolveCallback(ret); \n\ + } \n\ + }; \n\ + \n\ + [TheName].prototype.checkFulfillment = function(promise) { \n\ + var now = ++this.now; \n\ + if (now === [TheTotal]) { \n\ + if (this.asyncNeeded) { \n\ + async.invoke(this._callFunction, this, promise); \n\ + } else { \n\ + this._callFunction(promise); \n\ + } \n\ + \n\ + } \n\ + }; \n\ + \n\ + [TheName].prototype._resultCancelled = function() { \n\ + [CancellationCode] \n\ + }; \n\ + \n\ + return [TheName]; \n\ + }(tryCatch, errorObj, Promise, async); \n\ + "; + + code = code.replace(/\[TheName\]/g, name) + .replace(/\[TheTotal\]/g, total) + .replace(/\[ThePassedArguments\]/g, passedArguments) + .replace(/\[TheProperties\]/g, assignment) + .replace(/\[CancellationCode\]/g, cancellationCode); + + return new Function("tryCatch", "errorObj", "Promise", "async", code) + (tryCatch, errorObj, Promise, async); + }; + + var holderClasses = []; + var thenCallbacks = []; + var promiseSetters = []; + + for (var i = 0; i < 8; ++i) { + holderClasses.push(generateHolderClass(i + 1)); + thenCallbacks.push(thenCallback(i + 1)); + promiseSetters.push(promiseSetter(i + 1)); + } + + reject = function (reason) { + this._reject(reason); + }; +}} + +Promise.join = function () { + var last = arguments.length - 1; + var fn; + if (last > 0 && typeof arguments[last] === "function") { + fn = arguments[last]; + if (!true) { + if (last <= 8 && canEvaluate) { + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + var HolderClass = holderClasses[last - 1]; + var holder = new HolderClass(fn); + var callbacks = thenCallbacks; + + for (var i = 0; i < last; ++i) { + var maybePromise = tryConvertToPromise(arguments[i], ret); + if (maybePromise instanceof Promise) { + maybePromise = maybePromise._target(); + var bitField = maybePromise._bitField; + ; + if (((bitField & 50397184) === 0)) { + maybePromise._then(callbacks[i], reject, + undefined, ret, holder); + promiseSetters[i](maybePromise, holder); + holder.asyncNeeded = false; + } else if (((bitField & 33554432) !== 0)) { + callbacks[i].call(ret, + maybePromise._value(), holder); + } else if (((bitField & 16777216) !== 0)) { + ret._reject(maybePromise._reason()); + } else { + ret._cancel(); + } + } else { + callbacks[i].call(ret, maybePromise, holder); + } + } + + if (!ret._isFateSealed()) { + if (holder.asyncNeeded) { + var domain = getDomain(); + if (domain !== null) { + holder.fn = util.domainBind(domain, holder.fn); + } + } + ret._setAsyncGuaranteed(); + ret._setOnCancel(holder); + } + return ret; + } + } + } + var args = [].slice.call(arguments);; + if (fn) args.pop(); + var ret = new PromiseArray(args).promise(); + return fn !== undefined ? ret.spread(fn) : ret; +}; + +}; + +},{"./util":21}],13:[function(_dereq_,module,exports){ +"use strict"; +module.exports = +function(Promise, INTERNAL, tryConvertToPromise, apiRejection, debug) { +var util = _dereq_("./util"); +var tryCatch = util.tryCatch; + +Promise.method = function (fn) { + if (typeof fn !== "function") { + throw new Promise.TypeError("expecting a function but got " + util.classString(fn)); + } + return function () { + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + ret._pushContext(); + var value = tryCatch(fn).apply(this, arguments); + var promiseCreated = ret._popContext(); + debug.checkForgottenReturns( + value, promiseCreated, "Promise.method", ret); + ret._resolveFromSyncValue(value); + return ret; + }; +}; + +Promise.attempt = Promise["try"] = function (fn) { + if (typeof fn !== "function") { + return apiRejection("expecting a function but got " + util.classString(fn)); + } + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + ret._pushContext(); + var value; + if (arguments.length > 1) { + debug.deprecated("calling Promise.try with more than 1 argument"); + var arg = arguments[1]; + var ctx = arguments[2]; + value = util.isArray(arg) ? tryCatch(fn).apply(ctx, arg) + : tryCatch(fn).call(ctx, arg); + } else { + value = tryCatch(fn)(); + } + var promiseCreated = ret._popContext(); + debug.checkForgottenReturns( + value, promiseCreated, "Promise.try", ret); + ret._resolveFromSyncValue(value); + return ret; +}; + +Promise.prototype._resolveFromSyncValue = function (value) { + if (value === util.errorObj) { + this._rejectCallback(value.e, false); + } else { + this._resolveCallback(value, true); + } +}; +}; + +},{"./util":21}],14:[function(_dereq_,module,exports){ +"use strict"; +var util = _dereq_("./util"); +var maybeWrapAsError = util.maybeWrapAsError; +var errors = _dereq_("./errors"); +var OperationalError = errors.OperationalError; +var es5 = _dereq_("./es5"); + +function isUntypedError(obj) { + return obj instanceof Error && + es5.getPrototypeOf(obj) === Error.prototype; +} + +var rErrorKey = /^(?:name|message|stack|cause)$/; +function wrapAsOperationalError(obj) { + var ret; + if (isUntypedError(obj)) { + ret = new OperationalError(obj); + ret.name = obj.name; + ret.message = obj.message; + ret.stack = obj.stack; + var keys = es5.keys(obj); + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (!rErrorKey.test(key)) { + ret[key] = obj[key]; + } + } + return ret; + } + util.markAsOriginatingFromRejection(obj); + return obj; +} + +function nodebackForPromise(promise, multiArgs) { + return function(err, value) { + if (promise === null) return; + if (err) { + var wrapped = wrapAsOperationalError(maybeWrapAsError(err)); + promise._attachExtraTrace(wrapped); + promise._reject(wrapped); + } else if (!multiArgs) { + promise._fulfill(value); + } else { + var args = [].slice.call(arguments, 1);; + promise._fulfill(args); + } + promise = null; + }; +} + +module.exports = nodebackForPromise; + +},{"./errors":9,"./es5":10,"./util":21}],15:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function() { +var makeSelfResolutionError = function () { + return new TypeError("circular promise resolution chain\u000a\u000a See http://goo.gl/MqrFmX\u000a"); +}; +var reflectHandler = function() { + return new Promise.PromiseInspection(this._target()); +}; +var apiRejection = function(msg) { + return Promise.reject(new TypeError(msg)); +}; +function Proxyable() {} +var UNDEFINED_BINDING = {}; +var util = _dereq_("./util"); + +var getDomain; +if (util.isNode) { + getDomain = function() { + var ret = process.domain; + if (ret === undefined) ret = null; + return ret; + }; +} else { + getDomain = function() { + return null; + }; +} +util.notEnumerableProp(Promise, "_getDomain", getDomain); + +var es5 = _dereq_("./es5"); +var Async = _dereq_("./async"); +var async = new Async(); +es5.defineProperty(Promise, "_async", {value: async}); +var errors = _dereq_("./errors"); +var TypeError = Promise.TypeError = errors.TypeError; +Promise.RangeError = errors.RangeError; +var CancellationError = Promise.CancellationError = errors.CancellationError; +Promise.TimeoutError = errors.TimeoutError; +Promise.OperationalError = errors.OperationalError; +Promise.RejectionError = errors.OperationalError; +Promise.AggregateError = errors.AggregateError; +var INTERNAL = function(){}; +var APPLY = {}; +var NEXT_FILTER = {}; +var tryConvertToPromise = _dereq_("./thenables")(Promise, INTERNAL); +var PromiseArray = + _dereq_("./promise_array")(Promise, INTERNAL, + tryConvertToPromise, apiRejection, Proxyable); +var Context = _dereq_("./context")(Promise); + /*jshint unused:false*/ +var createContext = Context.create; +var debug = _dereq_("./debuggability")(Promise, Context); +var CapturedTrace = debug.CapturedTrace; +var PassThroughHandlerContext = + _dereq_("./finally")(Promise, tryConvertToPromise, NEXT_FILTER); +var catchFilter = _dereq_("./catch_filter")(NEXT_FILTER); +var nodebackForPromise = _dereq_("./nodeback"); +var errorObj = util.errorObj; +var tryCatch = util.tryCatch; +function check(self, executor) { + if (self == null || self.constructor !== Promise) { + throw new TypeError("the promise constructor cannot be invoked directly\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + if (typeof executor !== "function") { + throw new TypeError("expecting a function but got " + util.classString(executor)); + } + +} + +function Promise(executor) { + if (executor !== INTERNAL) { + check(this, executor); + } + this._bitField = 0; + this._fulfillmentHandler0 = undefined; + this._rejectionHandler0 = undefined; + this._promise0 = undefined; + this._receiver0 = undefined; + this._resolveFromExecutor(executor); + this._promiseCreated(); + this._fireEvent("promiseCreated", this); +} + +Promise.prototype.toString = function () { + return "[object Promise]"; +}; + +Promise.prototype.caught = Promise.prototype["catch"] = function (fn) { + var len = arguments.length; + if (len > 1) { + var catchInstances = new Array(len - 1), + j = 0, i; + for (i = 0; i < len - 1; ++i) { + var item = arguments[i]; + if (util.isObject(item)) { + catchInstances[j++] = item; + } else { + return apiRejection("Catch statement predicate: " + + "expecting an object but got " + util.classString(item)); + } + } + catchInstances.length = j; + fn = arguments[i]; + return this.then(undefined, catchFilter(catchInstances, fn, this)); + } + return this.then(undefined, fn); +}; + +Promise.prototype.reflect = function () { + return this._then(reflectHandler, + reflectHandler, undefined, this, undefined); +}; + +Promise.prototype.then = function (didFulfill, didReject) { + if (debug.warnings() && arguments.length > 0 && + typeof didFulfill !== "function" && + typeof didReject !== "function") { + var msg = ".then() only accepts functions but was passed: " + + util.classString(didFulfill); + if (arguments.length > 1) { + msg += ", " + util.classString(didReject); + } + this._warn(msg); + } + return this._then(didFulfill, didReject, undefined, undefined, undefined); +}; + +Promise.prototype.done = function (didFulfill, didReject) { + var promise = + this._then(didFulfill, didReject, undefined, undefined, undefined); + promise._setIsFinal(); +}; + +Promise.prototype.spread = function (fn) { + if (typeof fn !== "function") { + return apiRejection("expecting a function but got " + util.classString(fn)); + } + return this.all()._then(fn, undefined, undefined, APPLY, undefined); +}; + +Promise.prototype.toJSON = function () { + var ret = { + isFulfilled: false, + isRejected: false, + fulfillmentValue: undefined, + rejectionReason: undefined + }; + if (this.isFulfilled()) { + ret.fulfillmentValue = this.value(); + ret.isFulfilled = true; + } else if (this.isRejected()) { + ret.rejectionReason = this.reason(); + ret.isRejected = true; + } + return ret; +}; + +Promise.prototype.all = function () { + if (arguments.length > 0) { + this._warn(".all() was passed arguments but it does not take any"); + } + return new PromiseArray(this).promise(); +}; + +Promise.prototype.error = function (fn) { + return this.caught(util.originatesFromRejection, fn); +}; + +Promise.getNewLibraryCopy = module.exports; + +Promise.is = function (val) { + return val instanceof Promise; +}; + +Promise.fromNode = Promise.fromCallback = function(fn) { + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + var multiArgs = arguments.length > 1 ? !!Object(arguments[1]).multiArgs + : false; + var result = tryCatch(fn)(nodebackForPromise(ret, multiArgs)); + if (result === errorObj) { + ret._rejectCallback(result.e, true); + } + if (!ret._isFateSealed()) ret._setAsyncGuaranteed(); + return ret; +}; + +Promise.all = function (promises) { + return new PromiseArray(promises).promise(); +}; + +Promise.cast = function (obj) { + var ret = tryConvertToPromise(obj); + if (!(ret instanceof Promise)) { + ret = new Promise(INTERNAL); + ret._captureStackTrace(); + ret._setFulfilled(); + ret._rejectionHandler0 = obj; + } + return ret; +}; + +Promise.resolve = Promise.fulfilled = Promise.cast; + +Promise.reject = Promise.rejected = function (reason) { + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + ret._rejectCallback(reason, true); + return ret; +}; + +Promise.setScheduler = function(fn) { + if (typeof fn !== "function") { + throw new TypeError("expecting a function but got " + util.classString(fn)); + } + return async.setScheduler(fn); +}; + +Promise.prototype._then = function ( + didFulfill, + didReject, + _, receiver, + internalData +) { + var haveInternalData = internalData !== undefined; + var promise = haveInternalData ? internalData : new Promise(INTERNAL); + var target = this._target(); + var bitField = target._bitField; + + if (!haveInternalData) { + promise._propagateFrom(this, 3); + promise._captureStackTrace(); + if (receiver === undefined && + ((this._bitField & 2097152) !== 0)) { + if (!((bitField & 50397184) === 0)) { + receiver = this._boundValue(); + } else { + receiver = target === this ? undefined : this._boundTo; + } + } + this._fireEvent("promiseChained", this, promise); + } + + var domain = getDomain(); + if (!((bitField & 50397184) === 0)) { + var handler, value, settler = target._settlePromiseCtx; + if (((bitField & 33554432) !== 0)) { + value = target._rejectionHandler0; + handler = didFulfill; + } else if (((bitField & 16777216) !== 0)) { + value = target._fulfillmentHandler0; + handler = didReject; + target._unsetRejectionIsUnhandled(); + } else { + settler = target._settlePromiseLateCancellationObserver; + value = new CancellationError("late cancellation observer"); + target._attachExtraTrace(value); + handler = didReject; + } + + async.invoke(settler, target, { + handler: domain === null ? handler + : (typeof handler === "function" && + util.domainBind(domain, handler)), + promise: promise, + receiver: receiver, + value: value + }); + } else { + target._addCallbacks(didFulfill, didReject, promise, receiver, domain); + } + + return promise; +}; + +Promise.prototype._length = function () { + return this._bitField & 65535; +}; + +Promise.prototype._isFateSealed = function () { + return (this._bitField & 117506048) !== 0; +}; + +Promise.prototype._isFollowing = function () { + return (this._bitField & 67108864) === 67108864; +}; + +Promise.prototype._setLength = function (len) { + this._bitField = (this._bitField & -65536) | + (len & 65535); +}; + +Promise.prototype._setFulfilled = function () { + this._bitField = this._bitField | 33554432; + this._fireEvent("promiseFulfilled", this); +}; + +Promise.prototype._setRejected = function () { + this._bitField = this._bitField | 16777216; + this._fireEvent("promiseRejected", this); +}; + +Promise.prototype._setFollowing = function () { + this._bitField = this._bitField | 67108864; + this._fireEvent("promiseResolved", this); +}; + +Promise.prototype._setIsFinal = function () { + this._bitField = this._bitField | 4194304; +}; + +Promise.prototype._isFinal = function () { + return (this._bitField & 4194304) > 0; +}; + +Promise.prototype._unsetCancelled = function() { + this._bitField = this._bitField & (~65536); +}; + +Promise.prototype._setCancelled = function() { + this._bitField = this._bitField | 65536; + this._fireEvent("promiseCancelled", this); +}; + +Promise.prototype._setWillBeCancelled = function() { + this._bitField = this._bitField | 8388608; +}; + +Promise.prototype._setAsyncGuaranteed = function() { + if (async.hasCustomScheduler()) return; + this._bitField = this._bitField | 134217728; +}; + +Promise.prototype._receiverAt = function (index) { + var ret = index === 0 ? this._receiver0 : this[ + index * 4 - 4 + 3]; + if (ret === UNDEFINED_BINDING) { + return undefined; + } else if (ret === undefined && this._isBound()) { + return this._boundValue(); + } + return ret; +}; + +Promise.prototype._promiseAt = function (index) { + return this[ + index * 4 - 4 + 2]; +}; + +Promise.prototype._fulfillmentHandlerAt = function (index) { + return this[ + index * 4 - 4 + 0]; +}; + +Promise.prototype._rejectionHandlerAt = function (index) { + return this[ + index * 4 - 4 + 1]; +}; + +Promise.prototype._boundValue = function() {}; + +Promise.prototype._migrateCallback0 = function (follower) { + var bitField = follower._bitField; + var fulfill = follower._fulfillmentHandler0; + var reject = follower._rejectionHandler0; + var promise = follower._promise0; + var receiver = follower._receiverAt(0); + if (receiver === undefined) receiver = UNDEFINED_BINDING; + this._addCallbacks(fulfill, reject, promise, receiver, null); +}; + +Promise.prototype._migrateCallbackAt = function (follower, index) { + var fulfill = follower._fulfillmentHandlerAt(index); + var reject = follower._rejectionHandlerAt(index); + var promise = follower._promiseAt(index); + var receiver = follower._receiverAt(index); + if (receiver === undefined) receiver = UNDEFINED_BINDING; + this._addCallbacks(fulfill, reject, promise, receiver, null); +}; + +Promise.prototype._addCallbacks = function ( + fulfill, + reject, + promise, + receiver, + domain +) { + var index = this._length(); + + if (index >= 65535 - 4) { + index = 0; + this._setLength(0); + } + + if (index === 0) { + this._promise0 = promise; + this._receiver0 = receiver; + if (typeof fulfill === "function") { + this._fulfillmentHandler0 = + domain === null ? fulfill : util.domainBind(domain, fulfill); + } + if (typeof reject === "function") { + this._rejectionHandler0 = + domain === null ? reject : util.domainBind(domain, reject); + } + } else { + var base = index * 4 - 4; + this[base + 2] = promise; + this[base + 3] = receiver; + if (typeof fulfill === "function") { + this[base + 0] = + domain === null ? fulfill : util.domainBind(domain, fulfill); + } + if (typeof reject === "function") { + this[base + 1] = + domain === null ? reject : util.domainBind(domain, reject); + } + } + this._setLength(index + 1); + return index; +}; + +Promise.prototype._proxy = function (proxyable, arg) { + this._addCallbacks(undefined, undefined, arg, proxyable, null); +}; + +Promise.prototype._resolveCallback = function(value, shouldBind) { + if (((this._bitField & 117506048) !== 0)) return; + if (value === this) + return this._rejectCallback(makeSelfResolutionError(), false); + var maybePromise = tryConvertToPromise(value, this); + if (!(maybePromise instanceof Promise)) return this._fulfill(value); + + if (shouldBind) this._propagateFrom(maybePromise, 2); + + var promise = maybePromise._target(); + + if (promise === this) { + this._reject(makeSelfResolutionError()); + return; + } + + var bitField = promise._bitField; + if (((bitField & 50397184) === 0)) { + var len = this._length(); + if (len > 0) promise._migrateCallback0(this); + for (var i = 1; i < len; ++i) { + promise._migrateCallbackAt(this, i); + } + this._setFollowing(); + this._setLength(0); + this._setFollowee(promise); + } else if (((bitField & 33554432) !== 0)) { + this._fulfill(promise._value()); + } else if (((bitField & 16777216) !== 0)) { + this._reject(promise._reason()); + } else { + var reason = new CancellationError("late cancellation observer"); + promise._attachExtraTrace(reason); + this._reject(reason); + } +}; + +Promise.prototype._rejectCallback = +function(reason, synchronous, ignoreNonErrorWarnings) { + var trace = util.ensureErrorObject(reason); + var hasStack = trace === reason; + if (!hasStack && !ignoreNonErrorWarnings && debug.warnings()) { + var message = "a promise was rejected with a non-error: " + + util.classString(reason); + this._warn(message, true); + } + this._attachExtraTrace(trace, synchronous ? hasStack : false); + this._reject(reason); +}; + +Promise.prototype._resolveFromExecutor = function (executor) { + if (executor === INTERNAL) return; + var promise = this; + this._captureStackTrace(); + this._pushContext(); + var synchronous = true; + var r = this._execute(executor, function(value) { + promise._resolveCallback(value); + }, function (reason) { + promise._rejectCallback(reason, synchronous); + }); + synchronous = false; + this._popContext(); + + if (r !== undefined) { + promise._rejectCallback(r, true); + } +}; + +Promise.prototype._settlePromiseFromHandler = function ( + handler, receiver, value, promise +) { + var bitField = promise._bitField; + if (((bitField & 65536) !== 0)) return; + promise._pushContext(); + var x; + if (receiver === APPLY) { + if (!value || typeof value.length !== "number") { + x = errorObj; + x.e = new TypeError("cannot .spread() a non-array: " + + util.classString(value)); + } else { + x = tryCatch(handler).apply(this._boundValue(), value); + } + } else { + x = tryCatch(handler).call(receiver, value); + } + var promiseCreated = promise._popContext(); + bitField = promise._bitField; + if (((bitField & 65536) !== 0)) return; + + if (x === NEXT_FILTER) { + promise._reject(value); + } else if (x === errorObj) { + promise._rejectCallback(x.e, false); + } else { + debug.checkForgottenReturns(x, promiseCreated, "", promise, this); + promise._resolveCallback(x); + } +}; + +Promise.prototype._target = function() { + var ret = this; + while (ret._isFollowing()) ret = ret._followee(); + return ret; +}; + +Promise.prototype._followee = function() { + return this._rejectionHandler0; +}; + +Promise.prototype._setFollowee = function(promise) { + this._rejectionHandler0 = promise; +}; + +Promise.prototype._settlePromise = function(promise, handler, receiver, value) { + var isPromise = promise instanceof Promise; + var bitField = this._bitField; + var asyncGuaranteed = ((bitField & 134217728) !== 0); + if (((bitField & 65536) !== 0)) { + if (isPromise) promise._invokeInternalOnCancel(); + + if (receiver instanceof PassThroughHandlerContext && + receiver.isFinallyHandler()) { + receiver.cancelPromise = promise; + if (tryCatch(handler).call(receiver, value) === errorObj) { + promise._reject(errorObj.e); + } + } else if (handler === reflectHandler) { + promise._fulfill(reflectHandler.call(receiver)); + } else if (receiver instanceof Proxyable) { + receiver._promiseCancelled(promise); + } else if (isPromise || promise instanceof PromiseArray) { + promise._cancel(); + } else { + receiver.cancel(); + } + } else if (typeof handler === "function") { + if (!isPromise) { + handler.call(receiver, value, promise); + } else { + if (asyncGuaranteed) promise._setAsyncGuaranteed(); + this._settlePromiseFromHandler(handler, receiver, value, promise); + } + } else if (receiver instanceof Proxyable) { + if (!receiver._isResolved()) { + if (((bitField & 33554432) !== 0)) { + receiver._promiseFulfilled(value, promise); + } else { + receiver._promiseRejected(value, promise); + } + } + } else if (isPromise) { + if (asyncGuaranteed) promise._setAsyncGuaranteed(); + if (((bitField & 33554432) !== 0)) { + promise._fulfill(value); + } else { + promise._reject(value); + } + } +}; + +Promise.prototype._settlePromiseLateCancellationObserver = function(ctx) { + var handler = ctx.handler; + var promise = ctx.promise; + var receiver = ctx.receiver; + var value = ctx.value; + if (typeof handler === "function") { + if (!(promise instanceof Promise)) { + handler.call(receiver, value, promise); + } else { + this._settlePromiseFromHandler(handler, receiver, value, promise); + } + } else if (promise instanceof Promise) { + promise._reject(value); + } +}; + +Promise.prototype._settlePromiseCtx = function(ctx) { + this._settlePromise(ctx.promise, ctx.handler, ctx.receiver, ctx.value); +}; + +Promise.prototype._settlePromise0 = function(handler, value, bitField) { + var promise = this._promise0; + var receiver = this._receiverAt(0); + this._promise0 = undefined; + this._receiver0 = undefined; + this._settlePromise(promise, handler, receiver, value); +}; + +Promise.prototype._clearCallbackDataAtIndex = function(index) { + var base = index * 4 - 4; + this[base + 2] = + this[base + 3] = + this[base + 0] = + this[base + 1] = undefined; +}; + +Promise.prototype._fulfill = function (value) { + var bitField = this._bitField; + if (((bitField & 117506048) >>> 16)) return; + if (value === this) { + var err = makeSelfResolutionError(); + this._attachExtraTrace(err); + return this._reject(err); + } + this._setFulfilled(); + this._rejectionHandler0 = value; + + if ((bitField & 65535) > 0) { + if (((bitField & 134217728) !== 0)) { + this._settlePromises(); + } else { + async.settlePromises(this); + } + this._dereferenceTrace(); + } +}; + +Promise.prototype._reject = function (reason) { + var bitField = this._bitField; + if (((bitField & 117506048) >>> 16)) return; + this._setRejected(); + this._fulfillmentHandler0 = reason; + + if (this._isFinal()) { + return async.fatalError(reason, util.isNode); + } + + if ((bitField & 65535) > 0) { + async.settlePromises(this); + } else { + this._ensurePossibleRejectionHandled(); + } +}; + +Promise.prototype._fulfillPromises = function (len, value) { + for (var i = 1; i < len; i++) { + var handler = this._fulfillmentHandlerAt(i); + var promise = this._promiseAt(i); + var receiver = this._receiverAt(i); + this._clearCallbackDataAtIndex(i); + this._settlePromise(promise, handler, receiver, value); + } +}; + +Promise.prototype._rejectPromises = function (len, reason) { + for (var i = 1; i < len; i++) { + var handler = this._rejectionHandlerAt(i); + var promise = this._promiseAt(i); + var receiver = this._receiverAt(i); + this._clearCallbackDataAtIndex(i); + this._settlePromise(promise, handler, receiver, reason); + } +}; + +Promise.prototype._settlePromises = function () { + var bitField = this._bitField; + var len = (bitField & 65535); + + if (len > 0) { + if (((bitField & 16842752) !== 0)) { + var reason = this._fulfillmentHandler0; + this._settlePromise0(this._rejectionHandler0, reason, bitField); + this._rejectPromises(len, reason); + } else { + var value = this._rejectionHandler0; + this._settlePromise0(this._fulfillmentHandler0, value, bitField); + this._fulfillPromises(len, value); + } + this._setLength(0); + } + this._clearCancellationData(); +}; + +Promise.prototype._settledValue = function() { + var bitField = this._bitField; + if (((bitField & 33554432) !== 0)) { + return this._rejectionHandler0; + } else if (((bitField & 16777216) !== 0)) { + return this._fulfillmentHandler0; + } +}; + +function deferResolve(v) {this.promise._resolveCallback(v);} +function deferReject(v) {this.promise._rejectCallback(v, false);} + +Promise.defer = Promise.pending = function() { + debug.deprecated("Promise.defer", "new Promise"); + var promise = new Promise(INTERNAL); + return { + promise: promise, + resolve: deferResolve, + reject: deferReject + }; +}; + +util.notEnumerableProp(Promise, + "_makeSelfResolutionError", + makeSelfResolutionError); + +_dereq_("./method")(Promise, INTERNAL, tryConvertToPromise, apiRejection, + debug); +_dereq_("./bind")(Promise, INTERNAL, tryConvertToPromise, debug); +_dereq_("./cancel")(Promise, PromiseArray, apiRejection, debug); +_dereq_("./direct_resolve")(Promise); +_dereq_("./synchronous_inspection")(Promise); +_dereq_("./join")( + Promise, PromiseArray, tryConvertToPromise, INTERNAL, async, getDomain); +Promise.Promise = Promise; +Promise.version = "3.5.3"; + + util.toFastProperties(Promise); + util.toFastProperties(Promise.prototype); + function fillTypes(value) { + var p = new Promise(INTERNAL); + p._fulfillmentHandler0 = value; + p._rejectionHandler0 = value; + p._promise0 = value; + p._receiver0 = value; + } + // Complete slack tracking, opt out of field-type tracking and + // stabilize map + fillTypes({a: 1}); + fillTypes({b: 2}); + fillTypes({c: 3}); + fillTypes(1); + fillTypes(function(){}); + fillTypes(undefined); + fillTypes(false); + fillTypes(new Promise(INTERNAL)); + debug.setBounds(Async.firstLineError, util.lastLineError); + return Promise; + +}; + +},{"./async":1,"./bind":2,"./cancel":4,"./catch_filter":5,"./context":6,"./debuggability":7,"./direct_resolve":8,"./errors":9,"./es5":10,"./finally":11,"./join":12,"./method":13,"./nodeback":14,"./promise_array":16,"./synchronous_inspection":19,"./thenables":20,"./util":21}],16:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, INTERNAL, tryConvertToPromise, + apiRejection, Proxyable) { +var util = _dereq_("./util"); +var isArray = util.isArray; + +function toResolutionValue(val) { + switch(val) { + case -2: return []; + case -3: return {}; + case -6: return new Map(); + } +} + +function PromiseArray(values) { + var promise = this._promise = new Promise(INTERNAL); + if (values instanceof Promise) { + promise._propagateFrom(values, 3); + } + promise._setOnCancel(this); + this._values = values; + this._length = 0; + this._totalResolved = 0; + this._init(undefined, -2); +} +util.inherits(PromiseArray, Proxyable); + +PromiseArray.prototype.length = function () { + return this._length; +}; + +PromiseArray.prototype.promise = function () { + return this._promise; +}; + +PromiseArray.prototype._init = function init(_, resolveValueIfEmpty) { + var values = tryConvertToPromise(this._values, this._promise); + if (values instanceof Promise) { + values = values._target(); + var bitField = values._bitField; + ; + this._values = values; + + if (((bitField & 50397184) === 0)) { + this._promise._setAsyncGuaranteed(); + return values._then( + init, + this._reject, + undefined, + this, + resolveValueIfEmpty + ); + } else if (((bitField & 33554432) !== 0)) { + values = values._value(); + } else if (((bitField & 16777216) !== 0)) { + return this._reject(values._reason()); + } else { + return this._cancel(); + } + } + values = util.asArray(values); + if (values === null) { + var err = apiRejection( + "expecting an array or an iterable object but got " + util.classString(values)).reason(); + this._promise._rejectCallback(err, false); + return; + } + + if (values.length === 0) { + if (resolveValueIfEmpty === -5) { + this._resolveEmptyArray(); + } + else { + this._resolve(toResolutionValue(resolveValueIfEmpty)); + } + return; + } + this._iterate(values); +}; + +PromiseArray.prototype._iterate = function(values) { + var len = this.getActualLength(values.length); + this._length = len; + this._values = this.shouldCopyValues() ? new Array(len) : this._values; + var result = this._promise; + var isResolved = false; + var bitField = null; + for (var i = 0; i < len; ++i) { + var maybePromise = tryConvertToPromise(values[i], result); + + if (maybePromise instanceof Promise) { + maybePromise = maybePromise._target(); + bitField = maybePromise._bitField; + } else { + bitField = null; + } + + if (isResolved) { + if (bitField !== null) { + maybePromise.suppressUnhandledRejections(); + } + } else if (bitField !== null) { + if (((bitField & 50397184) === 0)) { + maybePromise._proxy(this, i); + this._values[i] = maybePromise; + } else if (((bitField & 33554432) !== 0)) { + isResolved = this._promiseFulfilled(maybePromise._value(), i); + } else if (((bitField & 16777216) !== 0)) { + isResolved = this._promiseRejected(maybePromise._reason(), i); + } else { + isResolved = this._promiseCancelled(i); + } + } else { + isResolved = this._promiseFulfilled(maybePromise, i); + } + } + if (!isResolved) result._setAsyncGuaranteed(); +}; + +PromiseArray.prototype._isResolved = function () { + return this._values === null; +}; + +PromiseArray.prototype._resolve = function (value) { + this._values = null; + this._promise._fulfill(value); +}; + +PromiseArray.prototype._cancel = function() { + if (this._isResolved() || !this._promise._isCancellable()) return; + this._values = null; + this._promise._cancel(); +}; + +PromiseArray.prototype._reject = function (reason) { + this._values = null; + this._promise._rejectCallback(reason, false); +}; + +PromiseArray.prototype._promiseFulfilled = function (value, index) { + this._values[index] = value; + var totalResolved = ++this._totalResolved; + if (totalResolved >= this._length) { + this._resolve(this._values); + return true; + } + return false; +}; + +PromiseArray.prototype._promiseCancelled = function() { + this._cancel(); + return true; +}; + +PromiseArray.prototype._promiseRejected = function (reason) { + this._totalResolved++; + this._reject(reason); + return true; +}; + +PromiseArray.prototype._resultCancelled = function() { + if (this._isResolved()) return; + var values = this._values; + this._cancel(); + if (values instanceof Promise) { + values.cancel(); + } else { + for (var i = 0; i < values.length; ++i) { + if (values[i] instanceof Promise) { + values[i].cancel(); + } + } + } +}; + +PromiseArray.prototype.shouldCopyValues = function () { + return true; +}; + +PromiseArray.prototype.getActualLength = function (len) { + return len; +}; + +return PromiseArray; +}; + +},{"./util":21}],17:[function(_dereq_,module,exports){ +"use strict"; +function arrayMove(src, srcIndex, dst, dstIndex, len) { + for (var j = 0; j < len; ++j) { + dst[j + dstIndex] = src[j + srcIndex]; + src[j + srcIndex] = void 0; + } +} + +function Queue(capacity) { + this._capacity = capacity; + this._length = 0; + this._front = 0; +} + +Queue.prototype._willBeOverCapacity = function (size) { + return this._capacity < size; +}; + +Queue.prototype._pushOne = function (arg) { + var length = this.length(); + this._checkCapacity(length + 1); + var i = (this._front + length) & (this._capacity - 1); + this[i] = arg; + this._length = length + 1; +}; + +Queue.prototype.push = function (fn, receiver, arg) { + var length = this.length() + 3; + if (this._willBeOverCapacity(length)) { + this._pushOne(fn); + this._pushOne(receiver); + this._pushOne(arg); + return; + } + var j = this._front + length - 3; + this._checkCapacity(length); + var wrapMask = this._capacity - 1; + this[(j + 0) & wrapMask] = fn; + this[(j + 1) & wrapMask] = receiver; + this[(j + 2) & wrapMask] = arg; + this._length = length; +}; + +Queue.prototype.shift = function () { + var front = this._front, + ret = this[front]; + + this[front] = undefined; + this._front = (front + 1) & (this._capacity - 1); + this._length--; + return ret; +}; + +Queue.prototype.length = function () { + return this._length; +}; + +Queue.prototype._checkCapacity = function (size) { + if (this._capacity < size) { + this._resizeTo(this._capacity << 1); + } +}; + +Queue.prototype._resizeTo = function (capacity) { + var oldCapacity = this._capacity; + this._capacity = capacity; + var front = this._front; + var length = this._length; + var moveItemsCount = (front + length) & (oldCapacity - 1); + arrayMove(this, 0, this, oldCapacity, moveItemsCount); +}; + +module.exports = Queue; + +},{}],18:[function(_dereq_,module,exports){ +"use strict"; +var util = _dereq_("./util"); +var schedule; +var noAsyncScheduler = function() { + throw new Error("No async scheduler available\u000a\u000a See http://goo.gl/MqrFmX\u000a"); +}; +var NativePromise = util.getNativePromise(); +if (util.isNode && typeof MutationObserver === "undefined") { + var GlobalSetImmediate = global.setImmediate; + var ProcessNextTick = process.nextTick; + schedule = util.isRecentNode + ? function(fn) { GlobalSetImmediate.call(global, fn); } + : function(fn) { ProcessNextTick.call(process, fn); }; +} else if (typeof NativePromise === "function" && + typeof NativePromise.resolve === "function") { + var nativePromise = NativePromise.resolve(); + schedule = function(fn) { + nativePromise.then(fn); + }; +} else if ((typeof MutationObserver !== "undefined") && + !(typeof window !== "undefined" && + window.navigator && + (window.navigator.standalone || window.cordova))) { + schedule = (function() { + var div = document.createElement("div"); + var opts = {attributes: true}; + var toggleScheduled = false; + var div2 = document.createElement("div"); + var o2 = new MutationObserver(function() { + div.classList.toggle("foo"); + toggleScheduled = false; + }); + o2.observe(div2, opts); + + var scheduleToggle = function() { + if (toggleScheduled) return; + toggleScheduled = true; + div2.classList.toggle("foo"); + }; + + return function schedule(fn) { + var o = new MutationObserver(function() { + o.disconnect(); + fn(); + }); + o.observe(div, opts); + scheduleToggle(); + }; + })(); +} else if (typeof setImmediate !== "undefined") { + schedule = function (fn) { + setImmediate(fn); + }; +} else if (typeof setTimeout !== "undefined") { + schedule = function (fn) { + setTimeout(fn, 0); + }; +} else { + schedule = noAsyncScheduler; +} +module.exports = schedule; + +},{"./util":21}],19:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise) { +function PromiseInspection(promise) { + if (promise !== undefined) { + promise = promise._target(); + this._bitField = promise._bitField; + this._settledValueField = promise._isFateSealed() + ? promise._settledValue() : undefined; + } + else { + this._bitField = 0; + this._settledValueField = undefined; + } +} + +PromiseInspection.prototype._settledValue = function() { + return this._settledValueField; +}; + +var value = PromiseInspection.prototype.value = function () { + if (!this.isFulfilled()) { + throw new TypeError("cannot get fulfillment value of a non-fulfilled promise\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + return this._settledValue(); +}; + +var reason = PromiseInspection.prototype.error = +PromiseInspection.prototype.reason = function () { + if (!this.isRejected()) { + throw new TypeError("cannot get rejection reason of a non-rejected promise\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + return this._settledValue(); +}; + +var isFulfilled = PromiseInspection.prototype.isFulfilled = function() { + return (this._bitField & 33554432) !== 0; +}; + +var isRejected = PromiseInspection.prototype.isRejected = function () { + return (this._bitField & 16777216) !== 0; +}; + +var isPending = PromiseInspection.prototype.isPending = function () { + return (this._bitField & 50397184) === 0; +}; + +var isResolved = PromiseInspection.prototype.isResolved = function () { + return (this._bitField & 50331648) !== 0; +}; + +PromiseInspection.prototype.isCancelled = function() { + return (this._bitField & 8454144) !== 0; +}; + +Promise.prototype.__isCancelled = function() { + return (this._bitField & 65536) === 65536; +}; + +Promise.prototype._isCancelled = function() { + return this._target().__isCancelled(); +}; + +Promise.prototype.isCancelled = function() { + return (this._target()._bitField & 8454144) !== 0; +}; + +Promise.prototype.isPending = function() { + return isPending.call(this._target()); +}; + +Promise.prototype.isRejected = function() { + return isRejected.call(this._target()); +}; + +Promise.prototype.isFulfilled = function() { + return isFulfilled.call(this._target()); +}; + +Promise.prototype.isResolved = function() { + return isResolved.call(this._target()); +}; + +Promise.prototype.value = function() { + return value.call(this._target()); +}; + +Promise.prototype.reason = function() { + var target = this._target(); + target._unsetRejectionIsUnhandled(); + return reason.call(target); +}; + +Promise.prototype._value = function() { + return this._settledValue(); +}; + +Promise.prototype._reason = function() { + this._unsetRejectionIsUnhandled(); + return this._settledValue(); +}; + +Promise.PromiseInspection = PromiseInspection; +}; + +},{}],20:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, INTERNAL) { +var util = _dereq_("./util"); +var errorObj = util.errorObj; +var isObject = util.isObject; + +function tryConvertToPromise(obj, context) { + if (isObject(obj)) { + if (obj instanceof Promise) return obj; + var then = getThen(obj); + if (then === errorObj) { + if (context) context._pushContext(); + var ret = Promise.reject(then.e); + if (context) context._popContext(); + return ret; + } else if (typeof then === "function") { + if (isAnyBluebirdPromise(obj)) { + var ret = new Promise(INTERNAL); + obj._then( + ret._fulfill, + ret._reject, + undefined, + ret, + null + ); + return ret; + } + return doThenable(obj, then, context); + } + } + return obj; +} + +function doGetThen(obj) { + return obj.then; +} + +function getThen(obj) { + try { + return doGetThen(obj); + } catch (e) { + errorObj.e = e; + return errorObj; + } +} + +var hasProp = {}.hasOwnProperty; +function isAnyBluebirdPromise(obj) { + try { + return hasProp.call(obj, "_promise0"); + } catch (e) { + return false; + } +} + +function doThenable(x, then, context) { + var promise = new Promise(INTERNAL); + var ret = promise; + if (context) context._pushContext(); + promise._captureStackTrace(); + if (context) context._popContext(); + var synchronous = true; + var result = util.tryCatch(then).call(x, resolve, reject); + synchronous = false; + + if (promise && result === errorObj) { + promise._rejectCallback(result.e, true, true); + promise = null; + } + + function resolve(value) { + if (!promise) return; + promise._resolveCallback(value); + promise = null; + } + + function reject(reason) { + if (!promise) return; + promise._rejectCallback(reason, synchronous, true); + promise = null; + } + return ret; +} + +return tryConvertToPromise; +}; + +},{"./util":21}],21:[function(_dereq_,module,exports){ +"use strict"; +var es5 = _dereq_("./es5"); +var canEvaluate = typeof navigator == "undefined"; + +var errorObj = {e: {}}; +var tryCatchTarget; +var globalObject = typeof self !== "undefined" ? self : + typeof window !== "undefined" ? window : + typeof global !== "undefined" ? global : + this !== undefined ? this : null; + +function tryCatcher() { + try { + var target = tryCatchTarget; + tryCatchTarget = null; + return target.apply(this, arguments); + } catch (e) { + errorObj.e = e; + return errorObj; + } +} +function tryCatch(fn) { + tryCatchTarget = fn; + return tryCatcher; +} + +var inherits = function(Child, Parent) { + var hasProp = {}.hasOwnProperty; + + function T() { + this.constructor = Child; + this.constructor$ = Parent; + for (var propertyName in Parent.prototype) { + if (hasProp.call(Parent.prototype, propertyName) && + propertyName.charAt(propertyName.length-1) !== "$" + ) { + this[propertyName + "$"] = Parent.prototype[propertyName]; + } + } + } + T.prototype = Parent.prototype; + Child.prototype = new T(); + return Child.prototype; +}; + + +function isPrimitive(val) { + return val == null || val === true || val === false || + typeof val === "string" || typeof val === "number"; + +} + +function isObject(value) { + return typeof value === "function" || + typeof value === "object" && value !== null; +} + +function maybeWrapAsError(maybeError) { + if (!isPrimitive(maybeError)) return maybeError; + + return new Error(safeToString(maybeError)); +} + +function withAppended(target, appendee) { + var len = target.length; + var ret = new Array(len + 1); + var i; + for (i = 0; i < len; ++i) { + ret[i] = target[i]; + } + ret[i] = appendee; + return ret; +} + +function getDataPropertyOrDefault(obj, key, defaultValue) { + if (es5.isES5) { + var desc = Object.getOwnPropertyDescriptor(obj, key); + + if (desc != null) { + return desc.get == null && desc.set == null + ? desc.value + : defaultValue; + } + } else { + return {}.hasOwnProperty.call(obj, key) ? obj[key] : undefined; + } +} + +function notEnumerableProp(obj, name, value) { + if (isPrimitive(obj)) return obj; + var descriptor = { + value: value, + configurable: true, + enumerable: false, + writable: true + }; + es5.defineProperty(obj, name, descriptor); + return obj; +} + +function thrower(r) { + throw r; +} + +var inheritedDataKeys = (function() { + var excludedPrototypes = [ + Array.prototype, + Object.prototype, + Function.prototype + ]; + + var isExcludedProto = function(val) { + for (var i = 0; i < excludedPrototypes.length; ++i) { + if (excludedPrototypes[i] === val) { + return true; + } + } + return false; + }; + + if (es5.isES5) { + var getKeys = Object.getOwnPropertyNames; + return function(obj) { + var ret = []; + var visitedKeys = Object.create(null); + while (obj != null && !isExcludedProto(obj)) { + var keys; + try { + keys = getKeys(obj); + } catch (e) { + return ret; + } + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (visitedKeys[key]) continue; + visitedKeys[key] = true; + var desc = Object.getOwnPropertyDescriptor(obj, key); + if (desc != null && desc.get == null && desc.set == null) { + ret.push(key); + } + } + obj = es5.getPrototypeOf(obj); + } + return ret; + }; + } else { + var hasProp = {}.hasOwnProperty; + return function(obj) { + if (isExcludedProto(obj)) return []; + var ret = []; + + /*jshint forin:false */ + enumeration: for (var key in obj) { + if (hasProp.call(obj, key)) { + ret.push(key); + } else { + for (var i = 0; i < excludedPrototypes.length; ++i) { + if (hasProp.call(excludedPrototypes[i], key)) { + continue enumeration; + } + } + ret.push(key); + } + } + return ret; + }; + } + +})(); + +var thisAssignmentPattern = /this\s*\.\s*\S+\s*=/; +function isClass(fn) { + try { + if (typeof fn === "function") { + var keys = es5.names(fn.prototype); + + var hasMethods = es5.isES5 && keys.length > 1; + var hasMethodsOtherThanConstructor = keys.length > 0 && + !(keys.length === 1 && keys[0] === "constructor"); + var hasThisAssignmentAndStaticMethods = + thisAssignmentPattern.test(fn + "") && es5.names(fn).length > 0; + + if (hasMethods || hasMethodsOtherThanConstructor || + hasThisAssignmentAndStaticMethods) { + return true; + } + } + return false; + } catch (e) { + return false; + } +} + +function toFastProperties(obj) { + /*jshint -W027,-W055,-W031*/ + function FakeConstructor() {} + FakeConstructor.prototype = obj; + var receiver = new FakeConstructor(); + function ic() { + return typeof receiver.foo; + } + ic(); + ic(); + return obj; + eval(obj); +} + +var rident = /^[a-z$_][a-z$_0-9]*$/i; +function isIdentifier(str) { + return rident.test(str); +} + +function filledRange(count, prefix, suffix) { + var ret = new Array(count); + for(var i = 0; i < count; ++i) { + ret[i] = prefix + i + suffix; + } + return ret; +} + +function safeToString(obj) { + try { + return obj + ""; + } catch (e) { + return "[no string representation]"; + } +} + +function isError(obj) { + return obj instanceof Error || + (obj !== null && + typeof obj === "object" && + typeof obj.message === "string" && + typeof obj.name === "string"); +} + +function markAsOriginatingFromRejection(e) { + try { + notEnumerableProp(e, "isOperational", true); + } + catch(ignore) {} +} + +function originatesFromRejection(e) { + if (e == null) return false; + return ((e instanceof Error["__BluebirdErrorTypes__"].OperationalError) || + e["isOperational"] === true); +} + +function canAttachTrace(obj) { + return isError(obj) && es5.propertyIsWritable(obj, "stack"); +} + +var ensureErrorObject = (function() { + if (!("stack" in new Error())) { + return function(value) { + if (canAttachTrace(value)) return value; + try {throw new Error(safeToString(value));} + catch(err) {return err;} + }; + } else { + return function(value) { + if (canAttachTrace(value)) return value; + return new Error(safeToString(value)); + }; + } +})(); + +function classString(obj) { + return {}.toString.call(obj); +} + +function copyDescriptors(from, to, filter) { + var keys = es5.names(from); + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (filter(key)) { + try { + es5.defineProperty(to, key, es5.getDescriptor(from, key)); + } catch (ignore) {} + } + } +} + +var asArray = function(v) { + if (es5.isArray(v)) { + return v; + } + return null; +}; + +if (typeof Symbol !== "undefined" && Symbol.iterator) { + var ArrayFrom = typeof Array.from === "function" ? function(v) { + return Array.from(v); + } : function(v) { + var ret = []; + var it = v[Symbol.iterator](); + var itResult; + while (!((itResult = it.next()).done)) { + ret.push(itResult.value); + } + return ret; + }; + + asArray = function(v) { + if (es5.isArray(v)) { + return v; + } else if (v != null && typeof v[Symbol.iterator] === "function") { + return ArrayFrom(v); + } + return null; + }; +} + +var isNode = typeof process !== "undefined" && + classString(process).toLowerCase() === "[object process]"; + +var hasEnvVariables = typeof process !== "undefined" && + typeof process.env !== "undefined"; + +function env(key) { + return hasEnvVariables ? process.env[key] : undefined; +} + +function getNativePromise() { + if (typeof Promise === "function") { + try { + var promise = new Promise(function(){}); + if ({}.toString.call(promise) === "[object Promise]") { + return Promise; + } + } catch (e) {} + } +} + +function domainBind(self, cb) { + return self.bind(cb); +} + +var ret = { + isClass: isClass, + isIdentifier: isIdentifier, + inheritedDataKeys: inheritedDataKeys, + getDataPropertyOrDefault: getDataPropertyOrDefault, + thrower: thrower, + isArray: es5.isArray, + asArray: asArray, + notEnumerableProp: notEnumerableProp, + isPrimitive: isPrimitive, + isObject: isObject, + isError: isError, + canEvaluate: canEvaluate, + errorObj: errorObj, + tryCatch: tryCatch, + inherits: inherits, + withAppended: withAppended, + maybeWrapAsError: maybeWrapAsError, + toFastProperties: toFastProperties, + filledRange: filledRange, + toString: safeToString, + canAttachTrace: canAttachTrace, + ensureErrorObject: ensureErrorObject, + originatesFromRejection: originatesFromRejection, + markAsOriginatingFromRejection: markAsOriginatingFromRejection, + classString: classString, + copyDescriptors: copyDescriptors, + hasDevTools: typeof chrome !== "undefined" && chrome && + typeof chrome.loadTimes === "function", + isNode: isNode, + hasEnvVariables: hasEnvVariables, + env: env, + global: globalObject, + getNativePromise: getNativePromise, + domainBind: domainBind +}; +ret.isRecentNode = ret.isNode && (function() { + var version = process.versions.node.split(".").map(Number); + return (version[0] === 0 && version[1] > 10) || (version[0] > 0); +})(); + +if (ret.isNode) ret.toFastProperties(process); + +try {throw new Error(); } catch (e) {ret.lastLineError = e;} +module.exports = ret; + +},{"./es5":10}]},{},[3])(3) +}); ;if (typeof window !== 'undefined' && window !== null) { window.P = window.Promise; } else if (typeof self !== 'undefined' && self !== null) { self.P = self.Promise; } \ No newline at end of file diff --git a/express-server/node_modules/bluebird/js/browser/bluebird.core.min.js b/express-server/node_modules/bluebird/js/browser/bluebird.core.min.js new file mode 100644 index 00000000..25fe9175 --- /dev/null +++ b/express-server/node_modules/bluebird/js/browser/bluebird.core.min.js @@ -0,0 +1,31 @@ +/* @preserve + * The MIT License (MIT) + * + * Copyright (c) 2013-2018 Petka Antonov + * + * 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. + * + */ +/** + * bluebird build version 3.5.3 + * Features enabled: core + * Features disabled: race, call_get, generators, map, nodeify, promisify, props, reduce, settle, some, using, timers, filter, any, each +*/ +!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;"undefined"!=typeof window?e=window:"undefined"!=typeof global?e=global:"undefined"!=typeof self&&(e=self),e.Promise=t()}}(function(){var t,e,n;return function r(t,e,n){function i(a,s){if(!e[a]){if(!t[a]){var c="function"==typeof _dereq_&&_dereq_;if(!s&&c)return c(a,!0);if(o)return o(a,!0);var l=new Error("Cannot find module '"+a+"'");throw l.code="MODULE_NOT_FOUND",l}var u=e[a]={exports:{}};t[a][0].call(u.exports,function(e){var n=t[a][1][e];return i(n?n:e)},u,u.exports,r,t,e,n)}return e[a].exports}for(var o="function"==typeof _dereq_&&_dereq_,a=0;a0;)c(t)}function c(t){var e=t.shift();if("function"!=typeof e)e._settlePromises();else{var n=t.shift(),r=t.shift();e.call(n,r)}}var l;try{throw new Error}catch(u){l=u}var p=t("./schedule"),f=t("./queue"),h=t("./util");r.prototype.setScheduler=function(t){var e=this._schedule;return this._schedule=t,this._customScheduler=!0,e},r.prototype.hasCustomScheduler=function(){return this._customScheduler},r.prototype.enableTrampoline=function(){this._trampolineEnabled=!0},r.prototype.disableTrampolineIfNecessary=function(){h.hasDevTools&&(this._trampolineEnabled=!1)},r.prototype.haveItemsQueued=function(){return this._isTickUsed||this._haveDrainedQueues},r.prototype.fatalError=function(t,e){e?(process.stderr.write("Fatal "+(t instanceof Error?t.stack:t)+"\n"),process.exit(2)):this.throwLater(t)},r.prototype.throwLater=function(t,e){if(1===arguments.length&&(e=t,t=function(){throw e}),"undefined"!=typeof setTimeout)setTimeout(function(){t(e)},0);else try{this._schedule(function(){t(e)})}catch(n){throw new Error("No async scheduler available\n\n See http://goo.gl/MqrFmX\n")}},h.hasDevTools?(r.prototype.invokeLater=function(t,e,n){this._trampolineEnabled?i.call(this,t,e,n):this._schedule(function(){setTimeout(function(){t.call(e,n)},100)})},r.prototype.invoke=function(t,e,n){this._trampolineEnabled?o.call(this,t,e,n):this._schedule(function(){t.call(e,n)})},r.prototype.settlePromises=function(t){this._trampolineEnabled?a.call(this,t):this._schedule(function(){t._settlePromises()})}):(r.prototype.invokeLater=i,r.prototype.invoke=o,r.prototype.settlePromises=a),r.prototype._drainQueues=function(){s(this._normalQueue),this._reset(),this._haveDrainedQueues=!0,s(this._lateQueue)},r.prototype._queueTick=function(){this._isTickUsed||(this._isTickUsed=!0,this._schedule(this.drainQueues))},r.prototype._reset=function(){this._isTickUsed=!1},e.exports=r,e.exports.firstLineError=l},{"./queue":17,"./schedule":18,"./util":21}],2:[function(t,e,n){"use strict";e.exports=function(t,e,n,r){var i=!1,o=function(t,e){this._reject(e)},a=function(t,e){e.promiseRejectionQueued=!0,e.bindingPromise._then(o,o,null,this,t)},s=function(t,e){0===(50397184&this._bitField)&&this._resolveCallback(e.target)},c=function(t,e){e.promiseRejectionQueued||this._reject(t)};t.prototype.bind=function(o){i||(i=!0,t.prototype._propagateFrom=r.propagateFromFunction(),t.prototype._boundValue=r.boundValueFunction());var l=n(o),u=new t(e);u._propagateFrom(this,1);var p=this._target();if(u._setBoundTo(l),l instanceof t){var f={promiseRejectionQueued:!1,promise:u,target:p,bindingPromise:l};p._then(e,a,void 0,u,f),l._then(s,c,void 0,u,f),u._setOnCancel(l)}else u._resolveCallback(p);return u},t.prototype._setBoundTo=function(t){void 0!==t?(this._bitField=2097152|this._bitField,this._boundTo=t):this._bitField=-2097153&this._bitField},t.prototype._isBound=function(){return 2097152===(2097152&this._bitField)},t.bind=function(e,n){return t.resolve(n).bind(e)}}},{}],3:[function(t,e,n){"use strict";function r(){try{Promise===o&&(Promise=i)}catch(t){}return o}var i;"undefined"!=typeof Promise&&(i=Promise);var o=t("./promise")();o.noConflict=r,e.exports=o},{"./promise":15}],4:[function(t,e,n){"use strict";e.exports=function(e,n,r,i){var o=t("./util"),a=o.tryCatch,s=o.errorObj,c=e._async;e.prototype["break"]=e.prototype.cancel=function(){if(!i.cancellation())return this._warn("cancellation is disabled");for(var t=this,e=t;t._isCancellable();){if(!t._cancelBy(e)){e._isFollowing()?e._followee().cancel():e._cancelBranched();break}var n=t._cancellationParent;if(null==n||!n._isCancellable()){t._isFollowing()?t._followee().cancel():t._cancelBranched();break}t._isFollowing()&&t._followee().cancel(),t._setWillBeCancelled(),e=t,t=n}},e.prototype._branchHasCancelled=function(){this._branchesRemainingToCancel--},e.prototype._enoughBranchesHaveCancelled=function(){return void 0===this._branchesRemainingToCancel||this._branchesRemainingToCancel<=0},e.prototype._cancelBy=function(t){return t===this?(this._branchesRemainingToCancel=0,this._invokeOnCancel(),!0):(this._branchHasCancelled(),this._enoughBranchesHaveCancelled()?(this._invokeOnCancel(),!0):!1)},e.prototype._cancelBranched=function(){this._enoughBranchesHaveCancelled()&&this._cancel()},e.prototype._cancel=function(){this._isCancellable()&&(this._setCancelled(),c.invoke(this._cancelPromises,this,void 0))},e.prototype._cancelPromises=function(){this._length()>0&&this._settlePromises()},e.prototype._unsetOnCancel=function(){this._onCancelField=void 0},e.prototype._isCancellable=function(){return this.isPending()&&!this._isCancelled()},e.prototype.isCancellable=function(){return this.isPending()&&!this.isCancelled()},e.prototype._doInvokeOnCancel=function(t,e){if(o.isArray(t))for(var n=0;n=0?o[t]:void 0}var i=!1,o=[];return t.prototype._promiseCreated=function(){},t.prototype._pushContext=function(){},t.prototype._popContext=function(){return null},t._peekContext=t.prototype._peekContext=function(){},e.prototype._pushContext=function(){void 0!==this._trace&&(this._trace._promiseCreated=null,o.push(this._trace))},e.prototype._popContext=function(){if(void 0!==this._trace){var t=o.pop(),e=t._promiseCreated;return t._promiseCreated=null,e}return null},e.CapturedTrace=null,e.create=n,e.deactivateLongStackTraces=function(){},e.activateLongStackTraces=function(){var n=t.prototype._pushContext,o=t.prototype._popContext,a=t._peekContext,s=t.prototype._peekContext,c=t.prototype._promiseCreated;e.deactivateLongStackTraces=function(){t.prototype._pushContext=n,t.prototype._popContext=o,t._peekContext=a,t.prototype._peekContext=s,t.prototype._promiseCreated=c,i=!1},i=!0,t.prototype._pushContext=e.prototype._pushContext,t.prototype._popContext=e.prototype._popContext,t._peekContext=t.prototype._peekContext=r,t.prototype._promiseCreated=function(){var t=this._peekContext();t&&null==t._promiseCreated&&(t._promiseCreated=this)}},e}},{}],7:[function(t,e,n){"use strict";e.exports=function(e,n){function r(t,e){return{promise:e}}function i(){return!1}function o(t,e,n){var r=this;try{t(e,n,function(t){if("function"!=typeof t)throw new TypeError("onCancel must be a function, got: "+H.toString(t));r._attachCancellationCallback(t)})}catch(i){return i}}function a(t){if(!this._isCancellable())return this;var e=this._onCancel();void 0!==e?H.isArray(e)?e.push(t):this._setOnCancel([e,t]):this._setOnCancel(t)}function s(){return this._onCancelField}function c(t){this._onCancelField=t}function l(){this._cancellationParent=void 0,this._onCancelField=void 0}function u(t,e){if(0!==(1&e)){this._cancellationParent=t;var n=t._branchesRemainingToCancel;void 0===n&&(n=0),t._branchesRemainingToCancel=n+1}0!==(2&e)&&t._isBound()&&this._setBoundTo(t._boundTo)}function p(t,e){0!==(2&e)&&t._isBound()&&this._setBoundTo(t._boundTo)}function f(){var t=this._boundTo;return void 0!==t&&t instanceof e?t.isFulfilled()?t.value():void 0:t}function h(){this._trace=new O(this._peekContext())}function _(t,e){if(V(t)){var n=this._trace;if(void 0!==n&&e&&(n=n._parent),void 0!==n)n.attachExtraTrace(t);else if(!t.__stackCleaned__){var r=k(t);H.notEnumerableProp(t,"stack",r.message+"\n"+r.stack.join("\n")),H.notEnumerableProp(t,"__stackCleaned__",!0)}}}function d(){this._trace=void 0}function v(t,e,n,r,i){if(void 0===t&&null!==e&&J){if(void 0!==i&&i._returnedNonUndefined())return;if(0===(65535&r._bitField))return;n&&(n+=" ");var o="",a="";if(e._trace){for(var s=e._trace.stack.split("\n"),c=w(s),l=c.length-1;l>=0;--l){var u=c[l];if(!q.test(u)){var p=u.match(G);p&&(o="at "+p[1]+":"+p[2]+":"+p[3]+" ");break}}if(c.length>0)for(var f=c[0],l=0;l0&&(a="\n"+s[l-1]);break}}var h="a promise was created in a "+n+"handler "+o+"but was not returned from it, see http://goo.gl/rRqMUw"+a;r._warn(h,!0,e)}}function y(t,e){var n=t+" is deprecated and will be removed in a future version.";return e&&(n+=" Use "+e+" instead."),g(n)}function g(t,n,r){if(st.warnings){var i,o=new I(t);if(n)r._attachExtraTrace(o);else if(st.longStackTraces&&(i=e._peekContext()))i.attachExtraTrace(o);else{var a=k(o);o.stack=a.message+"\n"+a.stack.join("\n")}nt("warning",o)||j(o,"",!0)}}function m(t,e){for(var n=0;n=0;--s)if(r[s]===o){a=s;break}for(var s=a;s>=0;--s){var c=r[s];if(e[i]!==c)break;e.pop(),i--}e=r}}function w(t){for(var e=[],n=0;n0&&"SyntaxError"!=t.name&&(e=e.slice(n)),e}function k(t){var e=t.stack,n=t.toString();return e="string"==typeof e&&e.length>0?E(t):[" (No stack trace)"],{message:n,stack:"SyntaxError"==t.name?e:w(e)}}function j(t,e,n){if("undefined"!=typeof console){var r;if(H.isObject(t)){var i=t.stack;r=e+W(i,t)}else r=e+String(t);"function"==typeof L?L(r,n):("function"==typeof console.log||"object"==typeof console.log)&&console.log(r)}}function F(t,e,n,r){var i=!1;try{"function"==typeof e&&(i=!0,"rejectionHandled"===t?e(r):e(n,r))}catch(o){U.throwLater(o)}"unhandledRejection"===t?nt(t,n,r)||i||j(n,"Unhandled rejection "):nt(t,r)}function T(t){var e;if("function"==typeof t)e="[function "+(t.name||"anonymous")+"]";else{e=t&&"function"==typeof t.toString?t.toString():H.toString(t);var n=/\[object [a-zA-Z0-9$_]+\]/;if(n.test(e))try{var r=JSON.stringify(t);e=r}catch(i){}0===e.length&&(e="(empty array)")}return"(<"+P(e)+">, no stack trace)"}function P(t){var e=41;return t.lengtha||0>s||!n||!r||n!==r||a>=s||(it=function(t){if(Q.test(t))return!0;var e=S(t);return e&&e.fileName===n&&a<=e.line&&e.line<=s?!0:!1})}}function O(t){this._parent=t,this._promisesCreated=0;var e=this._length=1+(void 0===t?0:t._length);at(this,O),e>32&&this.uncycle()}var A,N,L,B=e._getDomain,U=e._async,I=t("./errors").Warning,H=t("./util"),D=t("./es5"),V=H.canAttachTrace,Q=/[\\\/]bluebird[\\\/]js[\\\/](release|debug|instrumented)/,q=/\((?:timers\.js):\d+:\d+\)/,G=/[\/<\(](.+?):(\d+):(\d+)\)?\s*$/,M=null,W=null,$=!1,z=!(0==H.env("BLUEBIRD_DEBUG")||!H.env("BLUEBIRD_DEBUG")&&"development"!==H.env("NODE_ENV")),X=!(0==H.env("BLUEBIRD_WARNINGS")||!z&&!H.env("BLUEBIRD_WARNINGS")),K=!(0==H.env("BLUEBIRD_LONG_STACK_TRACES")||!z&&!H.env("BLUEBIRD_LONG_STACK_TRACES")),J=0!=H.env("BLUEBIRD_W_FORGOTTEN_RETURN")&&(X||!!H.env("BLUEBIRD_W_FORGOTTEN_RETURN"));e.prototype.suppressUnhandledRejections=function(){var t=this._target();t._bitField=-1048577&t._bitField|524288},e.prototype._ensurePossibleRejectionHandled=function(){if(0===(524288&this._bitField)){this._setRejectionIsUnhandled();var t=this;setTimeout(function(){t._notifyUnhandledRejection()},1)}},e.prototype._notifyUnhandledRejectionIsHandled=function(){F("rejectionHandled",A,void 0,this)},e.prototype._setReturnedNonUndefined=function(){this._bitField=268435456|this._bitField},e.prototype._returnedNonUndefined=function(){return 0!==(268435456&this._bitField)},e.prototype._notifyUnhandledRejection=function(){if(this._isRejectionUnhandled()){var t=this._settledValue();this._setUnhandledRejectionIsNotified(),F("unhandledRejection",N,t,this)}},e.prototype._setUnhandledRejectionIsNotified=function(){this._bitField=262144|this._bitField},e.prototype._unsetUnhandledRejectionIsNotified=function(){this._bitField=-262145&this._bitField},e.prototype._isUnhandledRejectionNotified=function(){return(262144&this._bitField)>0},e.prototype._setRejectionIsUnhandled=function(){this._bitField=1048576|this._bitField},e.prototype._unsetRejectionIsUnhandled=function(){this._bitField=-1048577&this._bitField,this._isUnhandledRejectionNotified()&&(this._unsetUnhandledRejectionIsNotified(),this._notifyUnhandledRejectionIsHandled())},e.prototype._isRejectionUnhandled=function(){return(1048576&this._bitField)>0},e.prototype._warn=function(t,e,n){return g(t,e,n||this)},e.onPossiblyUnhandledRejection=function(t){var e=B();N="function"==typeof t?null===e?t:H.domainBind(e,t):void 0},e.onUnhandledRejectionHandled=function(t){var e=B();A="function"==typeof t?null===e?t:H.domainBind(e,t):void 0};var Y=function(){};e.longStackTraces=function(){if(U.haveItemsQueued()&&!st.longStackTraces)throw new Error("cannot enable long stack traces after promises have been created\n\n See http://goo.gl/MqrFmX\n");if(!st.longStackTraces&&R()){var t=e.prototype._captureStackTrace,r=e.prototype._attachExtraTrace,i=e.prototype._dereferenceTrace;st.longStackTraces=!0,Y=function(){if(U.haveItemsQueued()&&!st.longStackTraces)throw new Error("cannot enable long stack traces after promises have been created\n\n See http://goo.gl/MqrFmX\n");e.prototype._captureStackTrace=t,e.prototype._attachExtraTrace=r,e.prototype._dereferenceTrace=i,n.deactivateLongStackTraces(),U.enableTrampoline(),st.longStackTraces=!1},e.prototype._captureStackTrace=h,e.prototype._attachExtraTrace=_,e.prototype._dereferenceTrace=d,n.activateLongStackTraces(),U.disableTrampolineIfNecessary()}},e.hasLongStackTraces=function(){return st.longStackTraces&&R()};var Z=function(){try{if("function"==typeof CustomEvent){var t=new CustomEvent("CustomEvent");return H.global.dispatchEvent(t),function(t,e){var n={detail:e,cancelable:!0};D.defineProperty(n,"promise",{value:e.promise}),D.defineProperty(n,"reason",{value:e.reason});var r=new CustomEvent(t.toLowerCase(),n);return!H.global.dispatchEvent(r)}}if("function"==typeof Event){var t=new Event("CustomEvent");return H.global.dispatchEvent(t),function(t,e){var n=new Event(t.toLowerCase(),{cancelable:!0});return n.detail=e,D.defineProperty(n,"promise",{value:e.promise}),D.defineProperty(n,"reason",{value:e.reason}),!H.global.dispatchEvent(n)}}var t=document.createEvent("CustomEvent");return t.initCustomEvent("testingtheevent",!1,!0,{}),H.global.dispatchEvent(t),function(t,e){var n=document.createEvent("CustomEvent");return n.initCustomEvent(t.toLowerCase(),!1,!0,e),!H.global.dispatchEvent(n)}}catch(e){}return function(){return!1}}(),tt=function(){return H.isNode?function(){return process.emit.apply(process,arguments)}:H.global?function(t){var e="on"+t.toLowerCase(),n=H.global[e];return n?(n.apply(H.global,[].slice.call(arguments,1)),!0):!1}:function(){return!1}}(),et={promiseCreated:r,promiseFulfilled:r,promiseRejected:r,promiseResolved:r,promiseCancelled:r,promiseChained:function(t,e,n){return{promise:e,child:n}},warning:function(t,e){return{warning:e}},unhandledRejection:function(t,e,n){return{reason:e,promise:n}},rejectionHandled:r},nt=function(t){var e=!1;try{e=tt.apply(null,arguments)}catch(n){U.throwLater(n),e=!0}var r=!1;try{r=Z(t,et[t].apply(null,arguments))}catch(n){U.throwLater(n),r=!0}return r||e};e.config=function(t){if(t=Object(t),"longStackTraces"in t&&(t.longStackTraces?e.longStackTraces():!t.longStackTraces&&e.hasLongStackTraces()&&Y()),"warnings"in t){var n=t.warnings;st.warnings=!!n,J=st.warnings,H.isObject(n)&&"wForgottenReturn"in n&&(J=!!n.wForgottenReturn)}if("cancellation"in t&&t.cancellation&&!st.cancellation){if(U.haveItemsQueued())throw new Error("cannot enable cancellation after promises are in use");e.prototype._clearCancellationData=l,e.prototype._propagateFrom=u,e.prototype._onCancel=s,e.prototype._setOnCancel=c,e.prototype._attachCancellationCallback=a,e.prototype._execute=o,rt=u,st.cancellation=!0}return"monitoring"in t&&(t.monitoring&&!st.monitoring?(st.monitoring=!0,e.prototype._fireEvent=nt):!t.monitoring&&st.monitoring&&(st.monitoring=!1,e.prototype._fireEvent=i)),e},e.prototype._fireEvent=i,e.prototype._execute=function(t,e,n){try{t(e,n)}catch(r){return r}},e.prototype._onCancel=function(){},e.prototype._setOnCancel=function(t){},e.prototype._attachCancellationCallback=function(t){},e.prototype._captureStackTrace=function(){},e.prototype._attachExtraTrace=function(){},e.prototype._dereferenceTrace=function(){},e.prototype._clearCancellationData=function(){},e.prototype._propagateFrom=function(t,e){};var rt=p,it=function(){return!1},ot=/[\/<\(]([^:\/]+):(\d+):(?:\d+)\)?\s*$/;H.inherits(O,Error),n.CapturedTrace=O,O.prototype.uncycle=function(){var t=this._length;if(!(2>t)){for(var e=[],n={},r=0,i=this;void 0!==i;++r)e.push(i),i=i._parent;t=this._length=r;for(var r=t-1;r>=0;--r){var o=e[r].stack;void 0===n[o]&&(n[o]=r)}for(var r=0;t>r;++r){var a=e[r].stack,s=n[a];if(void 0!==s&&s!==r){s>0&&(e[s-1]._parent=void 0,e[s-1]._length=1),e[r]._parent=void 0,e[r]._length=1;var c=r>0?e[r-1]:this;t-1>s?(c._parent=e[s+1],c._parent.uncycle(),c._length=c._parent._length+1):(c._parent=void 0,c._length=1);for(var l=c._length+1,u=r-2;u>=0;--u)e[u]._length=l,l++;return}}}},O.prototype.attachExtraTrace=function(t){if(!t.__stackCleaned__){this.uncycle();for(var e=k(t),n=e.message,r=[e.stack],i=this;void 0!==i;)r.push(w(i.stack.split("\n"))),i=i._parent;C(r),b(r),H.notEnumerableProp(t,"stack",m(n,r)),H.notEnumerableProp(t,"__stackCleaned__",!0)}};var at=function(){var t=/^\s*at\s*/,e=function(t,e){return"string"==typeof t?t:void 0!==e.name&&void 0!==e.message?e.toString():T(e)};if("number"==typeof Error.stackTraceLimit&&"function"==typeof Error.captureStackTrace){Error.stackTraceLimit+=6,M=t,W=e;var n=Error.captureStackTrace;return it=function(t){return Q.test(t)},function(t,e){Error.stackTraceLimit+=6,n(t,e),Error.stackTraceLimit-=6}}var r=new Error;if("string"==typeof r.stack&&r.stack.split("\n")[0].indexOf("stackDetection@")>=0)return M=/@/,W=e,$=!0,function(t){t.stack=(new Error).stack};var i;try{throw new Error}catch(o){i="stack"in o}return"stack"in r||!i||"number"!=typeof Error.stackTraceLimit?(W=function(t,e){return"string"==typeof t?t:"object"!=typeof e&&"function"!=typeof e||void 0===e.name||void 0===e.message?T(e):e.toString()},null):(M=t,W=e,function(t){Error.stackTraceLimit+=6;try{throw new Error}catch(e){t.stack=e.stack}Error.stackTraceLimit-=6})}([]);"undefined"!=typeof console&&"undefined"!=typeof console.warn&&(L=function(t){console.warn(t)},H.isNode&&process.stderr.isTTY?L=function(t,e){var n=e?"":"";console.warn(n+t+"\n")}:H.isNode||"string"!=typeof(new Error).stack||(L=function(t,e){console.warn("%c"+t,e?"color: darkorange":"color: red")}));var st={warnings:X,longStackTraces:!1,cancellation:!1,monitoring:!1};return K&&e.longStackTraces(),{longStackTraces:function(){return st.longStackTraces},warnings:function(){return st.warnings},cancellation:function(){return st.cancellation},monitoring:function(){return st.monitoring},propagateFromFunction:function(){return rt},boundValueFunction:function(){return f},checkForgottenReturns:v,setBounds:x,warn:g,deprecated:y,CapturedTrace:O,fireDomEvent:Z,fireGlobalEvent:tt}}},{"./errors":9,"./es5":10,"./util":21}],8:[function(t,e,n){"use strict";e.exports=function(t){function e(){return this.value}function n(){throw this.reason}t.prototype["return"]=t.prototype.thenReturn=function(n){return n instanceof t&&n.suppressUnhandledRejections(),this._then(e,void 0,void 0,{value:n},void 0)},t.prototype["throw"]=t.prototype.thenThrow=function(t){return this._then(n,void 0,void 0,{reason:t},void 0)},t.prototype.catchThrow=function(t){if(arguments.length<=1)return this._then(void 0,n,void 0,{reason:t},void 0);var e=arguments[1],r=function(){throw e};return this.caught(t,r)},t.prototype.catchReturn=function(n){if(arguments.length<=1)return n instanceof t&&n.suppressUnhandledRejections(),this._then(void 0,e,void 0,{value:n},void 0);var r=arguments[1];r instanceof t&&r.suppressUnhandledRejections();var i=function(){return r};return this.caught(n,i)}}},{}],9:[function(t,e,n){"use strict";function r(t,e){function n(r){return this instanceof n?(p(this,"message","string"==typeof r?r:e),p(this,"name",t),void(Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):Error.call(this))):new n(r)}return u(n,Error),n}function i(t){return this instanceof i?(p(this,"name","OperationalError"),p(this,"message",t),this.cause=t,this.isOperational=!0,void(t instanceof Error?(p(this,"message",t.message),p(this,"stack",t.stack)):Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor))):new i(t)}var o,a,s=t("./es5"),c=s.freeze,l=t("./util"),u=l.inherits,p=l.notEnumerableProp,f=r("Warning","warning"),h=r("CancellationError","cancellation error"),_=r("TimeoutError","timeout error"),d=r("AggregateError","aggregate error");try{o=TypeError,a=RangeError}catch(v){o=r("TypeError","type error"),a=r("RangeError","range error")}for(var y="join pop push shift unshift slice filter forEach some every map indexOf lastIndexOf reduce reduceRight sort reverse".split(" "),g=0;g1?t.cancelPromise._reject(e):t.cancelPromise._cancel(),t.cancelPromise=null,!0):!1}function s(){return l.call(this,this.promise._target()._settledValue())}function c(t){return a(this,t)?void 0:(f.e=t,f)}function l(t){var i=this.promise,l=this.handler;if(!this.called){this.called=!0;var u=this.isFinallyHandler()?l.call(i._boundValue()):l.call(i._boundValue(),t);if(u===r)return u;if(void 0!==u){i._setReturnedNonUndefined();var h=n(u,i);if(h instanceof e){if(null!=this.cancelPromise){if(h._isCancelled()){var _=new p("late cancellation observer");return i._attachExtraTrace(_),f.e=_,f}h.isPending()&&h._attachCancellationCallback(new o(this))}return h._then(s,c,void 0,this,void 0)}}}return i.isRejected()?(a(this),f.e=t,f):(a(this),t)}var u=t("./util"),p=e.CancellationError,f=u.errorObj,h=t("./catch_filter")(r);return i.prototype.isFinallyHandler=function(){return 0===this.type},o.prototype._resultCancelled=function(){a(this.finallyHandler)},e.prototype._passThrough=function(t,e,n,r){return"function"!=typeof t?this.then():this._then(n,r,void 0,new i(this,e,t),void 0)},e.prototype.lastly=e.prototype["finally"]=function(t){return this._passThrough(t,0,l,l)},e.prototype.tap=function(t){return this._passThrough(t,1,l)},e.prototype.tapCatch=function(t){var n=arguments.length;if(1===n)return this._passThrough(t,1,void 0,l);var r,i=new Array(n-1),o=0;for(r=0;n-1>r;++r){var a=arguments[r];if(!u.isObject(a))return e.reject(new TypeError("tapCatch statement predicate: expecting an object but got "+u.classString(a)));i[o++]=a}i.length=o;var s=arguments[r];return this._passThrough(h(i,s,this),1,void 0,l)},i}},{"./catch_filter":5,"./util":21}],12:[function(t,e,n){"use strict";e.exports=function(e,n,r,i,o,a){var s=t("./util");s.canEvaluate,s.tryCatch,s.errorObj;e.join=function(){var t,e=arguments.length-1;if(e>0&&"function"==typeof arguments[e]){t=arguments[e];var r}var i=[].slice.call(arguments);t&&i.pop();var r=new n(i).promise();return void 0!==t?r.spread(t):r}}},{"./util":21}],13:[function(t,e,n){"use strict";e.exports=function(e,n,r,i,o){var a=t("./util"),s=a.tryCatch;e.method=function(t){if("function"!=typeof t)throw new e.TypeError("expecting a function but got "+a.classString(t));return function(){var r=new e(n);r._captureStackTrace(),r._pushContext();var i=s(t).apply(this,arguments),a=r._popContext();return o.checkForgottenReturns(i,a,"Promise.method",r),r._resolveFromSyncValue(i),r}},e.attempt=e["try"]=function(t){if("function"!=typeof t)return i("expecting a function but got "+a.classString(t));var r=new e(n);r._captureStackTrace(),r._pushContext();var c;if(arguments.length>1){o.deprecated("calling Promise.try with more than 1 argument");var l=arguments[1],u=arguments[2];c=a.isArray(l)?s(t).apply(u,l):s(t).call(u,l)}else c=s(t)();var p=r._popContext();return o.checkForgottenReturns(c,p,"Promise.try",r),r._resolveFromSyncValue(c),r},e.prototype._resolveFromSyncValue=function(t){t===a.errorObj?this._rejectCallback(t.e,!1):this._resolveCallback(t,!0)}}},{"./util":21}],14:[function(t,e,n){"use strict";function r(t){return t instanceof Error&&u.getPrototypeOf(t)===Error.prototype}function i(t){var e;if(r(t)){e=new l(t),e.name=t.name,e.message=t.message,e.stack=t.stack;for(var n=u.keys(t),i=0;i1){var n,r=new Array(e-1),i=0;for(n=0;e-1>n;++n){var o=arguments[n];if(!h.isObject(o))return p("Catch statement predicate: expecting an object but got "+h.classString(o));r[i++]=o}return r.length=i,t=arguments[n],this.then(void 0,P(r,t,this))}return this.then(void 0,t)},i.prototype.reflect=function(){return this._then(u,u,void 0,this,void 0)},i.prototype.then=function(t,e){if(F.warnings()&&arguments.length>0&&"function"!=typeof t&&"function"!=typeof e){ +var n=".then() only accepts functions but was passed: "+h.classString(t);arguments.length>1&&(n+=", "+h.classString(e)),this._warn(n)}return this._then(t,e,void 0,void 0,void 0)},i.prototype.done=function(t,e){var n=this._then(t,e,void 0,void 0,void 0);n._setIsFinal()},i.prototype.spread=function(t){return"function"!=typeof t?p("expecting a function but got "+h.classString(t)):this.all()._then(t,void 0,void 0,C,void 0)},i.prototype.toJSON=function(){var t={isFulfilled:!1,isRejected:!1,fulfillmentValue:void 0,rejectionReason:void 0};return this.isFulfilled()?(t.fulfillmentValue=this.value(),t.isFulfilled=!0):this.isRejected()&&(t.rejectionReason=this.reason(),t.isRejected=!0),t},i.prototype.all=function(){return arguments.length>0&&this._warn(".all() was passed arguments but it does not take any"),new k(this).promise()},i.prototype.error=function(t){return this.caught(h.originatesFromRejection,t)},i.getNewLibraryCopy=e.exports,i.is=function(t){return t instanceof i},i.fromNode=i.fromCallback=function(t){var e=new i(b);e._captureStackTrace();var n=arguments.length>1?!!Object(arguments[1]).multiArgs:!1,r=x(t)(R(e,n));return r===S&&e._rejectCallback(r.e,!0),e._isFateSealed()||e._setAsyncGuaranteed(),e},i.all=function(t){return new k(t).promise()},i.cast=function(t){var e=E(t);return e instanceof i||(e=new i(b),e._captureStackTrace(),e._setFulfilled(),e._rejectionHandler0=t),e},i.resolve=i.fulfilled=i.cast,i.reject=i.rejected=function(t){var e=new i(b);return e._captureStackTrace(),e._rejectCallback(t,!0),e},i.setScheduler=function(t){if("function"!=typeof t)throw new g("expecting a function but got "+h.classString(t));return v.setScheduler(t)},i.prototype._then=function(t,e,n,r,o){var a=void 0!==o,s=a?o:new i(b),l=this._target(),u=l._bitField;a||(s._propagateFrom(this,3),s._captureStackTrace(),void 0===r&&0!==(2097152&this._bitField)&&(r=0!==(50397184&u)?this._boundValue():l===this?void 0:this._boundTo),this._fireEvent("promiseChained",this,s));var p=c();if(0!==(50397184&u)){var f,_,d=l._settlePromiseCtx;0!==(33554432&u)?(_=l._rejectionHandler0,f=t):0!==(16777216&u)?(_=l._fulfillmentHandler0,f=e,l._unsetRejectionIsUnhandled()):(d=l._settlePromiseLateCancellationObserver,_=new m("late cancellation observer"),l._attachExtraTrace(_),f=e),v.invoke(d,l,{handler:null===p?f:"function"==typeof f&&h.domainBind(p,f),promise:s,receiver:r,value:_})}else l._addCallbacks(t,e,s,r,p);return s},i.prototype._length=function(){return 65535&this._bitField},i.prototype._isFateSealed=function(){return 0!==(117506048&this._bitField)},i.prototype._isFollowing=function(){return 67108864===(67108864&this._bitField)},i.prototype._setLength=function(t){this._bitField=-65536&this._bitField|65535&t},i.prototype._setFulfilled=function(){this._bitField=33554432|this._bitField,this._fireEvent("promiseFulfilled",this)},i.prototype._setRejected=function(){this._bitField=16777216|this._bitField,this._fireEvent("promiseRejected",this)},i.prototype._setFollowing=function(){this._bitField=67108864|this._bitField,this._fireEvent("promiseResolved",this)},i.prototype._setIsFinal=function(){this._bitField=4194304|this._bitField},i.prototype._isFinal=function(){return(4194304&this._bitField)>0},i.prototype._unsetCancelled=function(){this._bitField=-65537&this._bitField},i.prototype._setCancelled=function(){this._bitField=65536|this._bitField,this._fireEvent("promiseCancelled",this)},i.prototype._setWillBeCancelled=function(){this._bitField=8388608|this._bitField},i.prototype._setAsyncGuaranteed=function(){v.hasCustomScheduler()||(this._bitField=134217728|this._bitField)},i.prototype._receiverAt=function(t){var e=0===t?this._receiver0:this[4*t-4+3];return e===f?void 0:void 0===e&&this._isBound()?this._boundValue():e},i.prototype._promiseAt=function(t){return this[4*t-4+2]},i.prototype._fulfillmentHandlerAt=function(t){return this[4*t-4+0]},i.prototype._rejectionHandlerAt=function(t){return this[4*t-4+1]},i.prototype._boundValue=function(){},i.prototype._migrateCallback0=function(t){var e=(t._bitField,t._fulfillmentHandler0),n=t._rejectionHandler0,r=t._promise0,i=t._receiverAt(0);void 0===i&&(i=f),this._addCallbacks(e,n,r,i,null)},i.prototype._migrateCallbackAt=function(t,e){var n=t._fulfillmentHandlerAt(e),r=t._rejectionHandlerAt(e),i=t._promiseAt(e),o=t._receiverAt(e);void 0===o&&(o=f),this._addCallbacks(n,r,i,o,null)},i.prototype._addCallbacks=function(t,e,n,r,i){var o=this._length();if(o>=65531&&(o=0,this._setLength(0)),0===o)this._promise0=n,this._receiver0=r,"function"==typeof t&&(this._fulfillmentHandler0=null===i?t:h.domainBind(i,t)),"function"==typeof e&&(this._rejectionHandler0=null===i?e:h.domainBind(i,e));else{var a=4*o-4;this[a+2]=n,this[a+3]=r,"function"==typeof t&&(this[a+0]=null===i?t:h.domainBind(i,t)),"function"==typeof e&&(this[a+1]=null===i?e:h.domainBind(i,e))}return this._setLength(o+1),o},i.prototype._proxy=function(t,e){this._addCallbacks(void 0,void 0,e,t,null)},i.prototype._resolveCallback=function(t,e){if(0===(117506048&this._bitField)){if(t===this)return this._rejectCallback(l(),!1);var n=E(t,this);if(!(n instanceof i))return this._fulfill(t);e&&this._propagateFrom(n,2);var r=n._target();if(r===this)return void this._reject(l());var o=r._bitField;if(0===(50397184&o)){var a=this._length();a>0&&r._migrateCallback0(this);for(var s=1;a>s;++s)r._migrateCallbackAt(this,s);this._setFollowing(),this._setLength(0),this._setFollowee(r)}else if(0!==(33554432&o))this._fulfill(r._value());else if(0!==(16777216&o))this._reject(r._reason());else{var c=new m("late cancellation observer");r._attachExtraTrace(c),this._reject(c)}}},i.prototype._rejectCallback=function(t,e,n){var r=h.ensureErrorObject(t),i=r===t;if(!i&&!n&&F.warnings()){var o="a promise was rejected with a non-error: "+h.classString(t);this._warn(o,!0)}this._attachExtraTrace(r,e?i:!1),this._reject(t)},i.prototype._resolveFromExecutor=function(t){if(t!==b){var e=this;this._captureStackTrace(),this._pushContext();var n=!0,r=this._execute(t,function(t){e._resolveCallback(t)},function(t){e._rejectCallback(t,n)});n=!1,this._popContext(),void 0!==r&&e._rejectCallback(r,!0)}},i.prototype._settlePromiseFromHandler=function(t,e,n,r){var i=r._bitField;if(0===(65536&i)){r._pushContext();var o;e===C?n&&"number"==typeof n.length?o=x(t).apply(this._boundValue(),n):(o=S,o.e=new g("cannot .spread() a non-array: "+h.classString(n))):o=x(t).call(e,n);var a=r._popContext();i=r._bitField,0===(65536&i)&&(o===w?r._reject(n):o===S?r._rejectCallback(o.e,!1):(F.checkForgottenReturns(o,a,"",r,this),r._resolveCallback(o)))}},i.prototype._target=function(){for(var t=this;t._isFollowing();)t=t._followee();return t},i.prototype._followee=function(){return this._rejectionHandler0},i.prototype._setFollowee=function(t){this._rejectionHandler0=t},i.prototype._settlePromise=function(t,e,r,o){var a=t instanceof i,s=this._bitField,c=0!==(134217728&s);0!==(65536&s)?(a&&t._invokeInternalOnCancel(),r instanceof T&&r.isFinallyHandler()?(r.cancelPromise=t,x(e).call(r,o)===S&&t._reject(S.e)):e===u?t._fulfill(u.call(r)):r instanceof n?r._promiseCancelled(t):a||t instanceof k?t._cancel():r.cancel()):"function"==typeof e?a?(c&&t._setAsyncGuaranteed(),this._settlePromiseFromHandler(e,r,o,t)):e.call(r,o,t):r instanceof n?r._isResolved()||(0!==(33554432&s)?r._promiseFulfilled(o,t):r._promiseRejected(o,t)):a&&(c&&t._setAsyncGuaranteed(),0!==(33554432&s)?t._fulfill(o):t._reject(o))},i.prototype._settlePromiseLateCancellationObserver=function(t){var e=t.handler,n=t.promise,r=t.receiver,o=t.value;"function"==typeof e?n instanceof i?this._settlePromiseFromHandler(e,r,o,n):e.call(r,o,n):n instanceof i&&n._reject(o)},i.prototype._settlePromiseCtx=function(t){this._settlePromise(t.promise,t.handler,t.receiver,t.value)},i.prototype._settlePromise0=function(t,e,n){var r=this._promise0,i=this._receiverAt(0);this._promise0=void 0,this._receiver0=void 0,this._settlePromise(r,t,i,e)},i.prototype._clearCallbackDataAtIndex=function(t){var e=4*t-4;this[e+2]=this[e+3]=this[e+0]=this[e+1]=void 0},i.prototype._fulfill=function(t){var e=this._bitField;if(!((117506048&e)>>>16)){if(t===this){var n=l();return this._attachExtraTrace(n),this._reject(n)}this._setFulfilled(),this._rejectionHandler0=t,(65535&e)>0&&(0!==(134217728&e)?this._settlePromises():v.settlePromises(this),this._dereferenceTrace())}},i.prototype._reject=function(t){var e=this._bitField;if(!((117506048&e)>>>16))return this._setRejected(),this._fulfillmentHandler0=t,this._isFinal()?v.fatalError(t,h.isNode):void((65535&e)>0?v.settlePromises(this):this._ensurePossibleRejectionHandled())},i.prototype._fulfillPromises=function(t,e){for(var n=1;t>n;n++){var r=this._fulfillmentHandlerAt(n),i=this._promiseAt(n),o=this._receiverAt(n);this._clearCallbackDataAtIndex(n),this._settlePromise(i,r,o,e)}},i.prototype._rejectPromises=function(t,e){for(var n=1;t>n;n++){var r=this._rejectionHandlerAt(n),i=this._promiseAt(n),o=this._receiverAt(n);this._clearCallbackDataAtIndex(n),this._settlePromise(i,r,o,e)}},i.prototype._settlePromises=function(){var t=this._bitField,e=65535&t;if(e>0){if(0!==(16842752&t)){var n=this._fulfillmentHandler0;this._settlePromise0(this._rejectionHandler0,n,t),this._rejectPromises(e,n)}else{var r=this._rejectionHandler0;this._settlePromise0(this._fulfillmentHandler0,r,t),this._fulfillPromises(e,r)}this._setLength(0)}this._clearCancellationData()},i.prototype._settledValue=function(){var t=this._bitField;return 0!==(33554432&t)?this._rejectionHandler0:0!==(16777216&t)?this._fulfillmentHandler0:void 0},i.defer=i.pending=function(){F.deprecated("Promise.defer","new Promise");var t=new i(b);return{promise:t,resolve:o,reject:a}},h.notEnumerableProp(i,"_makeSelfResolutionError",l),t("./method")(i,b,E,p,F),t("./bind")(i,b,E,F),t("./cancel")(i,k,p,F),t("./direct_resolve")(i),t("./synchronous_inspection")(i),t("./join")(i,k,E,b,v,c),i.Promise=i,i.version="3.5.3",h.toFastProperties(i),h.toFastProperties(i.prototype),s({a:1}),s({b:2}),s({c:3}),s(1),s(function(){}),s(void 0),s(!1),s(new i(b)),F.setBounds(d.firstLineError,h.lastLineError),i}},{"./async":1,"./bind":2,"./cancel":4,"./catch_filter":5,"./context":6,"./debuggability":7,"./direct_resolve":8,"./errors":9,"./es5":10,"./finally":11,"./join":12,"./method":13,"./nodeback":14,"./promise_array":16,"./synchronous_inspection":19,"./thenables":20,"./util":21}],16:[function(t,e,n){"use strict";e.exports=function(e,n,r,i,o){function a(t){switch(t){case-2:return[];case-3:return{};case-6:return new Map}}function s(t){var r=this._promise=new e(n);t instanceof e&&r._propagateFrom(t,3),r._setOnCancel(this),this._values=t,this._length=0,this._totalResolved=0,this._init(void 0,-2)}var c=t("./util");c.isArray;return c.inherits(s,o),s.prototype.length=function(){return this._length},s.prototype.promise=function(){return this._promise},s.prototype._init=function l(t,n){var o=r(this._values,this._promise);if(o instanceof e){o=o._target();var s=o._bitField;if(this._values=o,0===(50397184&s))return this._promise._setAsyncGuaranteed(),o._then(l,this._reject,void 0,this,n);if(0===(33554432&s))return 0!==(16777216&s)?this._reject(o._reason()):this._cancel();o=o._value()}if(o=c.asArray(o),null===o){var u=i("expecting an array or an iterable object but got "+c.classString(o)).reason();return void this._promise._rejectCallback(u,!1)}return 0===o.length?void(-5===n?this._resolveEmptyArray():this._resolve(a(n))):void this._iterate(o)},s.prototype._iterate=function(t){var n=this.getActualLength(t.length);this._length=n,this._values=this.shouldCopyValues()?new Array(n):this._values;for(var i=this._promise,o=!1,a=null,s=0;n>s;++s){var c=r(t[s],i);c instanceof e?(c=c._target(),a=c._bitField):a=null,o?null!==a&&c.suppressUnhandledRejections():null!==a?0===(50397184&a)?(c._proxy(this,s),this._values[s]=c):o=0!==(33554432&a)?this._promiseFulfilled(c._value(),s):0!==(16777216&a)?this._promiseRejected(c._reason(),s):this._promiseCancelled(s):o=this._promiseFulfilled(c,s)}o||i._setAsyncGuaranteed()},s.prototype._isResolved=function(){return null===this._values},s.prototype._resolve=function(t){this._values=null,this._promise._fulfill(t)},s.prototype._cancel=function(){!this._isResolved()&&this._promise._isCancellable()&&(this._values=null,this._promise._cancel())},s.prototype._reject=function(t){this._values=null,this._promise._rejectCallback(t,!1)},s.prototype._promiseFulfilled=function(t,e){this._values[e]=t;var n=++this._totalResolved;return n>=this._length?(this._resolve(this._values),!0):!1},s.prototype._promiseCancelled=function(){return this._cancel(),!0},s.prototype._promiseRejected=function(t){return this._totalResolved++,this._reject(t),!0},s.prototype._resultCancelled=function(){if(!this._isResolved()){var t=this._values;if(this._cancel(),t instanceof e)t.cancel();else for(var n=0;no;++o)n[o+r]=t[o+e],t[o+e]=void 0}function i(t){this._capacity=t,this._length=0,this._front=0}i.prototype._willBeOverCapacity=function(t){return this._capacityn;++n)i[n]=t[n];return i[n]=e,i}function l(t,e,n){if(!F.isES5)return{}.hasOwnProperty.call(t,e)?t[e]:void 0;var r=Object.getOwnPropertyDescriptor(t,e);return null!=r?null==r.get&&null==r.set?r.value:n:void 0}function u(t,e,n){if(o(t))return t;var r={value:n,configurable:!0,enumerable:!1,writable:!0};return F.defineProperty(t,e,r),t}function p(t){throw t}function f(t){try{if("function"==typeof t){var e=F.names(t.prototype),n=F.isES5&&e.length>1,r=e.length>0&&!(1===e.length&&"constructor"===e[0]),i=A.test(t+"")&&F.names(t).length>0;if(n||r||i)return!0}return!1}catch(o){return!1}}function h(t){function e(){}function n(){return typeof r.foo}e.prototype=t;var r=new e;return n(),n(),t}function _(t){return N.test(t)}function d(t,e,n){for(var r=new Array(t),i=0;t>i;++i)r[i]=e+i+n;return r}function v(t){try{return t+""}catch(e){return"[no string representation]"}}function y(t){return t instanceof Error||null!==t&&"object"==typeof t&&"string"==typeof t.message&&"string"==typeof t.name}function g(t){try{u(t,"isOperational",!0)}catch(e){}}function m(t){return null==t?!1:t instanceof Error.__BluebirdErrorTypes__.OperationalError||t.isOperational===!0}function b(t){return y(t)&&F.propertyIsWritable(t,"stack")}function C(t){return{}.toString.call(t)}function w(t,e,n){for(var r=F.names(t),i=0;i10||t[0]>0}(),D.isNode&&D.toFastProperties(process);try{throw new Error}catch(V){D.lastLineError=V}e.exports=D},{"./es5":10}]},{},[3])(3)}),"undefined"!=typeof window&&null!==window?window.P=window.Promise:"undefined"!=typeof self&&null!==self&&(self.P=self.Promise); \ No newline at end of file diff --git a/express-server/node_modules/bluebird/js/browser/bluebird.js b/express-server/node_modules/bluebird/js/browser/bluebird.js new file mode 100644 index 00000000..66c6c1c4 --- /dev/null +++ b/express-server/node_modules/bluebird/js/browser/bluebird.js @@ -0,0 +1,5647 @@ +/* @preserve + * The MIT License (MIT) + * + * Copyright (c) 2013-2018 Petka Antonov + * + * 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. + * + */ +/** + * bluebird build version 3.5.3 + * Features enabled: core, race, call_get, generators, map, nodeify, promisify, props, reduce, settle, some, using, timers, filter, any, each +*/ +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Promise=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof _dereq_=="function"&&_dereq_;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof _dereq_=="function"&&_dereq_;for(var o=0;o 0) { + _drainQueueStep(queue); + } +} + +function _drainQueueStep(queue) { + var fn = queue.shift(); + if (typeof fn !== "function") { + fn._settlePromises(); + } else { + var receiver = queue.shift(); + var arg = queue.shift(); + fn.call(receiver, arg); + } +} + +Async.prototype._drainQueues = function () { + _drainQueue(this._normalQueue); + this._reset(); + this._haveDrainedQueues = true; + _drainQueue(this._lateQueue); +}; + +Async.prototype._queueTick = function () { + if (!this._isTickUsed) { + this._isTickUsed = true; + this._schedule(this.drainQueues); + } +}; + +Async.prototype._reset = function () { + this._isTickUsed = false; +}; + +module.exports = Async; +module.exports.firstLineError = firstLineError; + +},{"./queue":26,"./schedule":29,"./util":36}],3:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, INTERNAL, tryConvertToPromise, debug) { +var calledBind = false; +var rejectThis = function(_, e) { + this._reject(e); +}; + +var targetRejected = function(e, context) { + context.promiseRejectionQueued = true; + context.bindingPromise._then(rejectThis, rejectThis, null, this, e); +}; + +var bindingResolved = function(thisArg, context) { + if (((this._bitField & 50397184) === 0)) { + this._resolveCallback(context.target); + } +}; + +var bindingRejected = function(e, context) { + if (!context.promiseRejectionQueued) this._reject(e); +}; + +Promise.prototype.bind = function (thisArg) { + if (!calledBind) { + calledBind = true; + Promise.prototype._propagateFrom = debug.propagateFromFunction(); + Promise.prototype._boundValue = debug.boundValueFunction(); + } + var maybePromise = tryConvertToPromise(thisArg); + var ret = new Promise(INTERNAL); + ret._propagateFrom(this, 1); + var target = this._target(); + ret._setBoundTo(maybePromise); + if (maybePromise instanceof Promise) { + var context = { + promiseRejectionQueued: false, + promise: ret, + target: target, + bindingPromise: maybePromise + }; + target._then(INTERNAL, targetRejected, undefined, ret, context); + maybePromise._then( + bindingResolved, bindingRejected, undefined, ret, context); + ret._setOnCancel(maybePromise); + } else { + ret._resolveCallback(target); + } + return ret; +}; + +Promise.prototype._setBoundTo = function (obj) { + if (obj !== undefined) { + this._bitField = this._bitField | 2097152; + this._boundTo = obj; + } else { + this._bitField = this._bitField & (~2097152); + } +}; + +Promise.prototype._isBound = function () { + return (this._bitField & 2097152) === 2097152; +}; + +Promise.bind = function (thisArg, value) { + return Promise.resolve(value).bind(thisArg); +}; +}; + +},{}],4:[function(_dereq_,module,exports){ +"use strict"; +var old; +if (typeof Promise !== "undefined") old = Promise; +function noConflict() { + try { if (Promise === bluebird) Promise = old; } + catch (e) {} + return bluebird; +} +var bluebird = _dereq_("./promise")(); +bluebird.noConflict = noConflict; +module.exports = bluebird; + +},{"./promise":22}],5:[function(_dereq_,module,exports){ +"use strict"; +var cr = Object.create; +if (cr) { + var callerCache = cr(null); + var getterCache = cr(null); + callerCache[" size"] = getterCache[" size"] = 0; +} + +module.exports = function(Promise) { +var util = _dereq_("./util"); +var canEvaluate = util.canEvaluate; +var isIdentifier = util.isIdentifier; + +var getMethodCaller; +var getGetter; +if (!true) { +var makeMethodCaller = function (methodName) { + return new Function("ensureMethod", " \n\ + return function(obj) { \n\ + 'use strict' \n\ + var len = this.length; \n\ + ensureMethod(obj, 'methodName'); \n\ + switch(len) { \n\ + case 1: return obj.methodName(this[0]); \n\ + case 2: return obj.methodName(this[0], this[1]); \n\ + case 3: return obj.methodName(this[0], this[1], this[2]); \n\ + case 0: return obj.methodName(); \n\ + default: \n\ + return obj.methodName.apply(obj, this); \n\ + } \n\ + }; \n\ + ".replace(/methodName/g, methodName))(ensureMethod); +}; + +var makeGetter = function (propertyName) { + return new Function("obj", " \n\ + 'use strict'; \n\ + return obj.propertyName; \n\ + ".replace("propertyName", propertyName)); +}; + +var getCompiled = function(name, compiler, cache) { + var ret = cache[name]; + if (typeof ret !== "function") { + if (!isIdentifier(name)) { + return null; + } + ret = compiler(name); + cache[name] = ret; + cache[" size"]++; + if (cache[" size"] > 512) { + var keys = Object.keys(cache); + for (var i = 0; i < 256; ++i) delete cache[keys[i]]; + cache[" size"] = keys.length - 256; + } + } + return ret; +}; + +getMethodCaller = function(name) { + return getCompiled(name, makeMethodCaller, callerCache); +}; + +getGetter = function(name) { + return getCompiled(name, makeGetter, getterCache); +}; +} + +function ensureMethod(obj, methodName) { + var fn; + if (obj != null) fn = obj[methodName]; + if (typeof fn !== "function") { + var message = "Object " + util.classString(obj) + " has no method '" + + util.toString(methodName) + "'"; + throw new Promise.TypeError(message); + } + return fn; +} + +function caller(obj) { + var methodName = this.pop(); + var fn = ensureMethod(obj, methodName); + return fn.apply(obj, this); +} +Promise.prototype.call = function (methodName) { + var args = [].slice.call(arguments, 1);; + if (!true) { + if (canEvaluate) { + var maybeCaller = getMethodCaller(methodName); + if (maybeCaller !== null) { + return this._then( + maybeCaller, undefined, undefined, args, undefined); + } + } + } + args.push(methodName); + return this._then(caller, undefined, undefined, args, undefined); +}; + +function namedGetter(obj) { + return obj[this]; +} +function indexedGetter(obj) { + var index = +this; + if (index < 0) index = Math.max(0, index + obj.length); + return obj[index]; +} +Promise.prototype.get = function (propertyName) { + var isIndex = (typeof propertyName === "number"); + var getter; + if (!isIndex) { + if (canEvaluate) { + var maybeGetter = getGetter(propertyName); + getter = maybeGetter !== null ? maybeGetter : namedGetter; + } else { + getter = namedGetter; + } + } else { + getter = indexedGetter; + } + return this._then(getter, undefined, undefined, propertyName, undefined); +}; +}; + +},{"./util":36}],6:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, PromiseArray, apiRejection, debug) { +var util = _dereq_("./util"); +var tryCatch = util.tryCatch; +var errorObj = util.errorObj; +var async = Promise._async; + +Promise.prototype["break"] = Promise.prototype.cancel = function() { + if (!debug.cancellation()) return this._warn("cancellation is disabled"); + + var promise = this; + var child = promise; + while (promise._isCancellable()) { + if (!promise._cancelBy(child)) { + if (child._isFollowing()) { + child._followee().cancel(); + } else { + child._cancelBranched(); + } + break; + } + + var parent = promise._cancellationParent; + if (parent == null || !parent._isCancellable()) { + if (promise._isFollowing()) { + promise._followee().cancel(); + } else { + promise._cancelBranched(); + } + break; + } else { + if (promise._isFollowing()) promise._followee().cancel(); + promise._setWillBeCancelled(); + child = promise; + promise = parent; + } + } +}; + +Promise.prototype._branchHasCancelled = function() { + this._branchesRemainingToCancel--; +}; + +Promise.prototype._enoughBranchesHaveCancelled = function() { + return this._branchesRemainingToCancel === undefined || + this._branchesRemainingToCancel <= 0; +}; + +Promise.prototype._cancelBy = function(canceller) { + if (canceller === this) { + this._branchesRemainingToCancel = 0; + this._invokeOnCancel(); + return true; + } else { + this._branchHasCancelled(); + if (this._enoughBranchesHaveCancelled()) { + this._invokeOnCancel(); + return true; + } + } + return false; +}; + +Promise.prototype._cancelBranched = function() { + if (this._enoughBranchesHaveCancelled()) { + this._cancel(); + } +}; + +Promise.prototype._cancel = function() { + if (!this._isCancellable()) return; + this._setCancelled(); + async.invoke(this._cancelPromises, this, undefined); +}; + +Promise.prototype._cancelPromises = function() { + if (this._length() > 0) this._settlePromises(); +}; + +Promise.prototype._unsetOnCancel = function() { + this._onCancelField = undefined; +}; + +Promise.prototype._isCancellable = function() { + return this.isPending() && !this._isCancelled(); +}; + +Promise.prototype.isCancellable = function() { + return this.isPending() && !this.isCancelled(); +}; + +Promise.prototype._doInvokeOnCancel = function(onCancelCallback, internalOnly) { + if (util.isArray(onCancelCallback)) { + for (var i = 0; i < onCancelCallback.length; ++i) { + this._doInvokeOnCancel(onCancelCallback[i], internalOnly); + } + } else if (onCancelCallback !== undefined) { + if (typeof onCancelCallback === "function") { + if (!internalOnly) { + var e = tryCatch(onCancelCallback).call(this._boundValue()); + if (e === errorObj) { + this._attachExtraTrace(e.e); + async.throwLater(e.e); + } + } + } else { + onCancelCallback._resultCancelled(this); + } + } +}; + +Promise.prototype._invokeOnCancel = function() { + var onCancelCallback = this._onCancel(); + this._unsetOnCancel(); + async.invoke(this._doInvokeOnCancel, this, onCancelCallback); +}; + +Promise.prototype._invokeInternalOnCancel = function() { + if (this._isCancellable()) { + this._doInvokeOnCancel(this._onCancel(), true); + this._unsetOnCancel(); + } +}; + +Promise.prototype._resultCancelled = function() { + this.cancel(); +}; + +}; + +},{"./util":36}],7:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(NEXT_FILTER) { +var util = _dereq_("./util"); +var getKeys = _dereq_("./es5").keys; +var tryCatch = util.tryCatch; +var errorObj = util.errorObj; + +function catchFilter(instances, cb, promise) { + return function(e) { + var boundTo = promise._boundValue(); + predicateLoop: for (var i = 0; i < instances.length; ++i) { + var item = instances[i]; + + if (item === Error || + (item != null && item.prototype instanceof Error)) { + if (e instanceof item) { + return tryCatch(cb).call(boundTo, e); + } + } else if (typeof item === "function") { + var matchesPredicate = tryCatch(item).call(boundTo, e); + if (matchesPredicate === errorObj) { + return matchesPredicate; + } else if (matchesPredicate) { + return tryCatch(cb).call(boundTo, e); + } + } else if (util.isObject(e)) { + var keys = getKeys(item); + for (var j = 0; j < keys.length; ++j) { + var key = keys[j]; + if (item[key] != e[key]) { + continue predicateLoop; + } + } + return tryCatch(cb).call(boundTo, e); + } + } + return NEXT_FILTER; + }; +} + +return catchFilter; +}; + +},{"./es5":13,"./util":36}],8:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise) { +var longStackTraces = false; +var contextStack = []; + +Promise.prototype._promiseCreated = function() {}; +Promise.prototype._pushContext = function() {}; +Promise.prototype._popContext = function() {return null;}; +Promise._peekContext = Promise.prototype._peekContext = function() {}; + +function Context() { + this._trace = new Context.CapturedTrace(peekContext()); +} +Context.prototype._pushContext = function () { + if (this._trace !== undefined) { + this._trace._promiseCreated = null; + contextStack.push(this._trace); + } +}; + +Context.prototype._popContext = function () { + if (this._trace !== undefined) { + var trace = contextStack.pop(); + var ret = trace._promiseCreated; + trace._promiseCreated = null; + return ret; + } + return null; +}; + +function createContext() { + if (longStackTraces) return new Context(); +} + +function peekContext() { + var lastIndex = contextStack.length - 1; + if (lastIndex >= 0) { + return contextStack[lastIndex]; + } + return undefined; +} +Context.CapturedTrace = null; +Context.create = createContext; +Context.deactivateLongStackTraces = function() {}; +Context.activateLongStackTraces = function() { + var Promise_pushContext = Promise.prototype._pushContext; + var Promise_popContext = Promise.prototype._popContext; + var Promise_PeekContext = Promise._peekContext; + var Promise_peekContext = Promise.prototype._peekContext; + var Promise_promiseCreated = Promise.prototype._promiseCreated; + Context.deactivateLongStackTraces = function() { + Promise.prototype._pushContext = Promise_pushContext; + Promise.prototype._popContext = Promise_popContext; + Promise._peekContext = Promise_PeekContext; + Promise.prototype._peekContext = Promise_peekContext; + Promise.prototype._promiseCreated = Promise_promiseCreated; + longStackTraces = false; + }; + longStackTraces = true; + Promise.prototype._pushContext = Context.prototype._pushContext; + Promise.prototype._popContext = Context.prototype._popContext; + Promise._peekContext = Promise.prototype._peekContext = peekContext; + Promise.prototype._promiseCreated = function() { + var ctx = this._peekContext(); + if (ctx && ctx._promiseCreated == null) ctx._promiseCreated = this; + }; +}; +return Context; +}; + +},{}],9:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, Context) { +var getDomain = Promise._getDomain; +var async = Promise._async; +var Warning = _dereq_("./errors").Warning; +var util = _dereq_("./util"); +var es5 = _dereq_("./es5"); +var canAttachTrace = util.canAttachTrace; +var unhandledRejectionHandled; +var possiblyUnhandledRejection; +var bluebirdFramePattern = + /[\\\/]bluebird[\\\/]js[\\\/](release|debug|instrumented)/; +var nodeFramePattern = /\((?:timers\.js):\d+:\d+\)/; +var parseLinePattern = /[\/<\(](.+?):(\d+):(\d+)\)?\s*$/; +var stackFramePattern = null; +var formatStack = null; +var indentStackFrames = false; +var printWarning; +var debugging = !!(util.env("BLUEBIRD_DEBUG") != 0 && + (true || + util.env("BLUEBIRD_DEBUG") || + util.env("NODE_ENV") === "development")); + +var warnings = !!(util.env("BLUEBIRD_WARNINGS") != 0 && + (debugging || util.env("BLUEBIRD_WARNINGS"))); + +var longStackTraces = !!(util.env("BLUEBIRD_LONG_STACK_TRACES") != 0 && + (debugging || util.env("BLUEBIRD_LONG_STACK_TRACES"))); + +var wForgottenReturn = util.env("BLUEBIRD_W_FORGOTTEN_RETURN") != 0 && + (warnings || !!util.env("BLUEBIRD_W_FORGOTTEN_RETURN")); + +Promise.prototype.suppressUnhandledRejections = function() { + var target = this._target(); + target._bitField = ((target._bitField & (~1048576)) | + 524288); +}; + +Promise.prototype._ensurePossibleRejectionHandled = function () { + if ((this._bitField & 524288) !== 0) return; + this._setRejectionIsUnhandled(); + var self = this; + setTimeout(function() { + self._notifyUnhandledRejection(); + }, 1); +}; + +Promise.prototype._notifyUnhandledRejectionIsHandled = function () { + fireRejectionEvent("rejectionHandled", + unhandledRejectionHandled, undefined, this); +}; + +Promise.prototype._setReturnedNonUndefined = function() { + this._bitField = this._bitField | 268435456; +}; + +Promise.prototype._returnedNonUndefined = function() { + return (this._bitField & 268435456) !== 0; +}; + +Promise.prototype._notifyUnhandledRejection = function () { + if (this._isRejectionUnhandled()) { + var reason = this._settledValue(); + this._setUnhandledRejectionIsNotified(); + fireRejectionEvent("unhandledRejection", + possiblyUnhandledRejection, reason, this); + } +}; + +Promise.prototype._setUnhandledRejectionIsNotified = function () { + this._bitField = this._bitField | 262144; +}; + +Promise.prototype._unsetUnhandledRejectionIsNotified = function () { + this._bitField = this._bitField & (~262144); +}; + +Promise.prototype._isUnhandledRejectionNotified = function () { + return (this._bitField & 262144) > 0; +}; + +Promise.prototype._setRejectionIsUnhandled = function () { + this._bitField = this._bitField | 1048576; +}; + +Promise.prototype._unsetRejectionIsUnhandled = function () { + this._bitField = this._bitField & (~1048576); + if (this._isUnhandledRejectionNotified()) { + this._unsetUnhandledRejectionIsNotified(); + this._notifyUnhandledRejectionIsHandled(); + } +}; + +Promise.prototype._isRejectionUnhandled = function () { + return (this._bitField & 1048576) > 0; +}; + +Promise.prototype._warn = function(message, shouldUseOwnTrace, promise) { + return warn(message, shouldUseOwnTrace, promise || this); +}; + +Promise.onPossiblyUnhandledRejection = function (fn) { + var domain = getDomain(); + possiblyUnhandledRejection = + typeof fn === "function" ? (domain === null ? + fn : util.domainBind(domain, fn)) + : undefined; +}; + +Promise.onUnhandledRejectionHandled = function (fn) { + var domain = getDomain(); + unhandledRejectionHandled = + typeof fn === "function" ? (domain === null ? + fn : util.domainBind(domain, fn)) + : undefined; +}; + +var disableLongStackTraces = function() {}; +Promise.longStackTraces = function () { + if (async.haveItemsQueued() && !config.longStackTraces) { + throw new Error("cannot enable long stack traces after promises have been created\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + if (!config.longStackTraces && longStackTracesIsSupported()) { + var Promise_captureStackTrace = Promise.prototype._captureStackTrace; + var Promise_attachExtraTrace = Promise.prototype._attachExtraTrace; + var Promise_dereferenceTrace = Promise.prototype._dereferenceTrace; + config.longStackTraces = true; + disableLongStackTraces = function() { + if (async.haveItemsQueued() && !config.longStackTraces) { + throw new Error("cannot enable long stack traces after promises have been created\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + Promise.prototype._captureStackTrace = Promise_captureStackTrace; + Promise.prototype._attachExtraTrace = Promise_attachExtraTrace; + Promise.prototype._dereferenceTrace = Promise_dereferenceTrace; + Context.deactivateLongStackTraces(); + async.enableTrampoline(); + config.longStackTraces = false; + }; + Promise.prototype._captureStackTrace = longStackTracesCaptureStackTrace; + Promise.prototype._attachExtraTrace = longStackTracesAttachExtraTrace; + Promise.prototype._dereferenceTrace = longStackTracesDereferenceTrace; + Context.activateLongStackTraces(); + async.disableTrampolineIfNecessary(); + } +}; + +Promise.hasLongStackTraces = function () { + return config.longStackTraces && longStackTracesIsSupported(); +}; + +var fireDomEvent = (function() { + try { + if (typeof CustomEvent === "function") { + var event = new CustomEvent("CustomEvent"); + util.global.dispatchEvent(event); + return function(name, event) { + var eventData = { + detail: event, + cancelable: true + }; + es5.defineProperty( + eventData, "promise", {value: event.promise}); + es5.defineProperty(eventData, "reason", {value: event.reason}); + var domEvent = new CustomEvent(name.toLowerCase(), eventData); + return !util.global.dispatchEvent(domEvent); + }; + } else if (typeof Event === "function") { + var event = new Event("CustomEvent"); + util.global.dispatchEvent(event); + return function(name, event) { + var domEvent = new Event(name.toLowerCase(), { + cancelable: true + }); + domEvent.detail = event; + es5.defineProperty(domEvent, "promise", {value: event.promise}); + es5.defineProperty(domEvent, "reason", {value: event.reason}); + return !util.global.dispatchEvent(domEvent); + }; + } else { + var event = document.createEvent("CustomEvent"); + event.initCustomEvent("testingtheevent", false, true, {}); + util.global.dispatchEvent(event); + return function(name, event) { + var domEvent = document.createEvent("CustomEvent"); + domEvent.initCustomEvent(name.toLowerCase(), false, true, + event); + return !util.global.dispatchEvent(domEvent); + }; + } + } catch (e) {} + return function() { + return false; + }; +})(); + +var fireGlobalEvent = (function() { + if (util.isNode) { + return function() { + return process.emit.apply(process, arguments); + }; + } else { + if (!util.global) { + return function() { + return false; + }; + } + return function(name) { + var methodName = "on" + name.toLowerCase(); + var method = util.global[methodName]; + if (!method) return false; + method.apply(util.global, [].slice.call(arguments, 1)); + return true; + }; + } +})(); + +function generatePromiseLifecycleEventObject(name, promise) { + return {promise: promise}; +} + +var eventToObjectGenerator = { + promiseCreated: generatePromiseLifecycleEventObject, + promiseFulfilled: generatePromiseLifecycleEventObject, + promiseRejected: generatePromiseLifecycleEventObject, + promiseResolved: generatePromiseLifecycleEventObject, + promiseCancelled: generatePromiseLifecycleEventObject, + promiseChained: function(name, promise, child) { + return {promise: promise, child: child}; + }, + warning: function(name, warning) { + return {warning: warning}; + }, + unhandledRejection: function (name, reason, promise) { + return {reason: reason, promise: promise}; + }, + rejectionHandled: generatePromiseLifecycleEventObject +}; + +var activeFireEvent = function (name) { + var globalEventFired = false; + try { + globalEventFired = fireGlobalEvent.apply(null, arguments); + } catch (e) { + async.throwLater(e); + globalEventFired = true; + } + + var domEventFired = false; + try { + domEventFired = fireDomEvent(name, + eventToObjectGenerator[name].apply(null, arguments)); + } catch (e) { + async.throwLater(e); + domEventFired = true; + } + + return domEventFired || globalEventFired; +}; + +Promise.config = function(opts) { + opts = Object(opts); + if ("longStackTraces" in opts) { + if (opts.longStackTraces) { + Promise.longStackTraces(); + } else if (!opts.longStackTraces && Promise.hasLongStackTraces()) { + disableLongStackTraces(); + } + } + if ("warnings" in opts) { + var warningsOption = opts.warnings; + config.warnings = !!warningsOption; + wForgottenReturn = config.warnings; + + if (util.isObject(warningsOption)) { + if ("wForgottenReturn" in warningsOption) { + wForgottenReturn = !!warningsOption.wForgottenReturn; + } + } + } + if ("cancellation" in opts && opts.cancellation && !config.cancellation) { + if (async.haveItemsQueued()) { + throw new Error( + "cannot enable cancellation after promises are in use"); + } + Promise.prototype._clearCancellationData = + cancellationClearCancellationData; + Promise.prototype._propagateFrom = cancellationPropagateFrom; + Promise.prototype._onCancel = cancellationOnCancel; + Promise.prototype._setOnCancel = cancellationSetOnCancel; + Promise.prototype._attachCancellationCallback = + cancellationAttachCancellationCallback; + Promise.prototype._execute = cancellationExecute; + propagateFromFunction = cancellationPropagateFrom; + config.cancellation = true; + } + if ("monitoring" in opts) { + if (opts.monitoring && !config.monitoring) { + config.monitoring = true; + Promise.prototype._fireEvent = activeFireEvent; + } else if (!opts.monitoring && config.monitoring) { + config.monitoring = false; + Promise.prototype._fireEvent = defaultFireEvent; + } + } + return Promise; +}; + +function defaultFireEvent() { return false; } + +Promise.prototype._fireEvent = defaultFireEvent; +Promise.prototype._execute = function(executor, resolve, reject) { + try { + executor(resolve, reject); + } catch (e) { + return e; + } +}; +Promise.prototype._onCancel = function () {}; +Promise.prototype._setOnCancel = function (handler) { ; }; +Promise.prototype._attachCancellationCallback = function(onCancel) { + ; +}; +Promise.prototype._captureStackTrace = function () {}; +Promise.prototype._attachExtraTrace = function () {}; +Promise.prototype._dereferenceTrace = function () {}; +Promise.prototype._clearCancellationData = function() {}; +Promise.prototype._propagateFrom = function (parent, flags) { + ; + ; +}; + +function cancellationExecute(executor, resolve, reject) { + var promise = this; + try { + executor(resolve, reject, function(onCancel) { + if (typeof onCancel !== "function") { + throw new TypeError("onCancel must be a function, got: " + + util.toString(onCancel)); + } + promise._attachCancellationCallback(onCancel); + }); + } catch (e) { + return e; + } +} + +function cancellationAttachCancellationCallback(onCancel) { + if (!this._isCancellable()) return this; + + var previousOnCancel = this._onCancel(); + if (previousOnCancel !== undefined) { + if (util.isArray(previousOnCancel)) { + previousOnCancel.push(onCancel); + } else { + this._setOnCancel([previousOnCancel, onCancel]); + } + } else { + this._setOnCancel(onCancel); + } +} + +function cancellationOnCancel() { + return this._onCancelField; +} + +function cancellationSetOnCancel(onCancel) { + this._onCancelField = onCancel; +} + +function cancellationClearCancellationData() { + this._cancellationParent = undefined; + this._onCancelField = undefined; +} + +function cancellationPropagateFrom(parent, flags) { + if ((flags & 1) !== 0) { + this._cancellationParent = parent; + var branchesRemainingToCancel = parent._branchesRemainingToCancel; + if (branchesRemainingToCancel === undefined) { + branchesRemainingToCancel = 0; + } + parent._branchesRemainingToCancel = branchesRemainingToCancel + 1; + } + if ((flags & 2) !== 0 && parent._isBound()) { + this._setBoundTo(parent._boundTo); + } +} + +function bindingPropagateFrom(parent, flags) { + if ((flags & 2) !== 0 && parent._isBound()) { + this._setBoundTo(parent._boundTo); + } +} +var propagateFromFunction = bindingPropagateFrom; + +function boundValueFunction() { + var ret = this._boundTo; + if (ret !== undefined) { + if (ret instanceof Promise) { + if (ret.isFulfilled()) { + return ret.value(); + } else { + return undefined; + } + } + } + return ret; +} + +function longStackTracesCaptureStackTrace() { + this._trace = new CapturedTrace(this._peekContext()); +} + +function longStackTracesAttachExtraTrace(error, ignoreSelf) { + if (canAttachTrace(error)) { + var trace = this._trace; + if (trace !== undefined) { + if (ignoreSelf) trace = trace._parent; + } + if (trace !== undefined) { + trace.attachExtraTrace(error); + } else if (!error.__stackCleaned__) { + var parsed = parseStackAndMessage(error); + util.notEnumerableProp(error, "stack", + parsed.message + "\n" + parsed.stack.join("\n")); + util.notEnumerableProp(error, "__stackCleaned__", true); + } + } +} + +function longStackTracesDereferenceTrace() { + this._trace = undefined; +} + +function checkForgottenReturns(returnValue, promiseCreated, name, promise, + parent) { + if (returnValue === undefined && promiseCreated !== null && + wForgottenReturn) { + if (parent !== undefined && parent._returnedNonUndefined()) return; + if ((promise._bitField & 65535) === 0) return; + + if (name) name = name + " "; + var handlerLine = ""; + var creatorLine = ""; + if (promiseCreated._trace) { + var traceLines = promiseCreated._trace.stack.split("\n"); + var stack = cleanStack(traceLines); + for (var i = stack.length - 1; i >= 0; --i) { + var line = stack[i]; + if (!nodeFramePattern.test(line)) { + var lineMatches = line.match(parseLinePattern); + if (lineMatches) { + handlerLine = "at " + lineMatches[1] + + ":" + lineMatches[2] + ":" + lineMatches[3] + " "; + } + break; + } + } + + if (stack.length > 0) { + var firstUserLine = stack[0]; + for (var i = 0; i < traceLines.length; ++i) { + + if (traceLines[i] === firstUserLine) { + if (i > 0) { + creatorLine = "\n" + traceLines[i - 1]; + } + break; + } + } + + } + } + var msg = "a promise was created in a " + name + + "handler " + handlerLine + "but was not returned from it, " + + "see http://goo.gl/rRqMUw" + + creatorLine; + promise._warn(msg, true, promiseCreated); + } +} + +function deprecated(name, replacement) { + var message = name + + " is deprecated and will be removed in a future version."; + if (replacement) message += " Use " + replacement + " instead."; + return warn(message); +} + +function warn(message, shouldUseOwnTrace, promise) { + if (!config.warnings) return; + var warning = new Warning(message); + var ctx; + if (shouldUseOwnTrace) { + promise._attachExtraTrace(warning); + } else if (config.longStackTraces && (ctx = Promise._peekContext())) { + ctx.attachExtraTrace(warning); + } else { + var parsed = parseStackAndMessage(warning); + warning.stack = parsed.message + "\n" + parsed.stack.join("\n"); + } + + if (!activeFireEvent("warning", warning)) { + formatAndLogError(warning, "", true); + } +} + +function reconstructStack(message, stacks) { + for (var i = 0; i < stacks.length - 1; ++i) { + stacks[i].push("From previous event:"); + stacks[i] = stacks[i].join("\n"); + } + if (i < stacks.length) { + stacks[i] = stacks[i].join("\n"); + } + return message + "\n" + stacks.join("\n"); +} + +function removeDuplicateOrEmptyJumps(stacks) { + for (var i = 0; i < stacks.length; ++i) { + if (stacks[i].length === 0 || + ((i + 1 < stacks.length) && stacks[i][0] === stacks[i+1][0])) { + stacks.splice(i, 1); + i--; + } + } +} + +function removeCommonRoots(stacks) { + var current = stacks[0]; + for (var i = 1; i < stacks.length; ++i) { + var prev = stacks[i]; + var currentLastIndex = current.length - 1; + var currentLastLine = current[currentLastIndex]; + var commonRootMeetPoint = -1; + + for (var j = prev.length - 1; j >= 0; --j) { + if (prev[j] === currentLastLine) { + commonRootMeetPoint = j; + break; + } + } + + for (var j = commonRootMeetPoint; j >= 0; --j) { + var line = prev[j]; + if (current[currentLastIndex] === line) { + current.pop(); + currentLastIndex--; + } else { + break; + } + } + current = prev; + } +} + +function cleanStack(stack) { + var ret = []; + for (var i = 0; i < stack.length; ++i) { + var line = stack[i]; + var isTraceLine = " (No stack trace)" === line || + stackFramePattern.test(line); + var isInternalFrame = isTraceLine && shouldIgnore(line); + if (isTraceLine && !isInternalFrame) { + if (indentStackFrames && line.charAt(0) !== " ") { + line = " " + line; + } + ret.push(line); + } + } + return ret; +} + +function stackFramesAsArray(error) { + var stack = error.stack.replace(/\s+$/g, "").split("\n"); + for (var i = 0; i < stack.length; ++i) { + var line = stack[i]; + if (" (No stack trace)" === line || stackFramePattern.test(line)) { + break; + } + } + if (i > 0 && error.name != "SyntaxError") { + stack = stack.slice(i); + } + return stack; +} + +function parseStackAndMessage(error) { + var stack = error.stack; + var message = error.toString(); + stack = typeof stack === "string" && stack.length > 0 + ? stackFramesAsArray(error) : [" (No stack trace)"]; + return { + message: message, + stack: error.name == "SyntaxError" ? stack : cleanStack(stack) + }; +} + +function formatAndLogError(error, title, isSoft) { + if (typeof console !== "undefined") { + var message; + if (util.isObject(error)) { + var stack = error.stack; + message = title + formatStack(stack, error); + } else { + message = title + String(error); + } + if (typeof printWarning === "function") { + printWarning(message, isSoft); + } else if (typeof console.log === "function" || + typeof console.log === "object") { + console.log(message); + } + } +} + +function fireRejectionEvent(name, localHandler, reason, promise) { + var localEventFired = false; + try { + if (typeof localHandler === "function") { + localEventFired = true; + if (name === "rejectionHandled") { + localHandler(promise); + } else { + localHandler(reason, promise); + } + } + } catch (e) { + async.throwLater(e); + } + + if (name === "unhandledRejection") { + if (!activeFireEvent(name, reason, promise) && !localEventFired) { + formatAndLogError(reason, "Unhandled rejection "); + } + } else { + activeFireEvent(name, promise); + } +} + +function formatNonError(obj) { + var str; + if (typeof obj === "function") { + str = "[function " + + (obj.name || "anonymous") + + "]"; + } else { + str = obj && typeof obj.toString === "function" + ? obj.toString() : util.toString(obj); + var ruselessToString = /\[object [a-zA-Z0-9$_]+\]/; + if (ruselessToString.test(str)) { + try { + var newStr = JSON.stringify(obj); + str = newStr; + } + catch(e) { + + } + } + if (str.length === 0) { + str = "(empty array)"; + } + } + return ("(<" + snip(str) + ">, no stack trace)"); +} + +function snip(str) { + var maxChars = 41; + if (str.length < maxChars) { + return str; + } + return str.substr(0, maxChars - 3) + "..."; +} + +function longStackTracesIsSupported() { + return typeof captureStackTrace === "function"; +} + +var shouldIgnore = function() { return false; }; +var parseLineInfoRegex = /[\/<\(]([^:\/]+):(\d+):(?:\d+)\)?\s*$/; +function parseLineInfo(line) { + var matches = line.match(parseLineInfoRegex); + if (matches) { + return { + fileName: matches[1], + line: parseInt(matches[2], 10) + }; + } +} + +function setBounds(firstLineError, lastLineError) { + if (!longStackTracesIsSupported()) return; + var firstStackLines = firstLineError.stack.split("\n"); + var lastStackLines = lastLineError.stack.split("\n"); + var firstIndex = -1; + var lastIndex = -1; + var firstFileName; + var lastFileName; + for (var i = 0; i < firstStackLines.length; ++i) { + var result = parseLineInfo(firstStackLines[i]); + if (result) { + firstFileName = result.fileName; + firstIndex = result.line; + break; + } + } + for (var i = 0; i < lastStackLines.length; ++i) { + var result = parseLineInfo(lastStackLines[i]); + if (result) { + lastFileName = result.fileName; + lastIndex = result.line; + break; + } + } + if (firstIndex < 0 || lastIndex < 0 || !firstFileName || !lastFileName || + firstFileName !== lastFileName || firstIndex >= lastIndex) { + return; + } + + shouldIgnore = function(line) { + if (bluebirdFramePattern.test(line)) return true; + var info = parseLineInfo(line); + if (info) { + if (info.fileName === firstFileName && + (firstIndex <= info.line && info.line <= lastIndex)) { + return true; + } + } + return false; + }; +} + +function CapturedTrace(parent) { + this._parent = parent; + this._promisesCreated = 0; + var length = this._length = 1 + (parent === undefined ? 0 : parent._length); + captureStackTrace(this, CapturedTrace); + if (length > 32) this.uncycle(); +} +util.inherits(CapturedTrace, Error); +Context.CapturedTrace = CapturedTrace; + +CapturedTrace.prototype.uncycle = function() { + var length = this._length; + if (length < 2) return; + var nodes = []; + var stackToIndex = {}; + + for (var i = 0, node = this; node !== undefined; ++i) { + nodes.push(node); + node = node._parent; + } + length = this._length = i; + for (var i = length - 1; i >= 0; --i) { + var stack = nodes[i].stack; + if (stackToIndex[stack] === undefined) { + stackToIndex[stack] = i; + } + } + for (var i = 0; i < length; ++i) { + var currentStack = nodes[i].stack; + var index = stackToIndex[currentStack]; + if (index !== undefined && index !== i) { + if (index > 0) { + nodes[index - 1]._parent = undefined; + nodes[index - 1]._length = 1; + } + nodes[i]._parent = undefined; + nodes[i]._length = 1; + var cycleEdgeNode = i > 0 ? nodes[i - 1] : this; + + if (index < length - 1) { + cycleEdgeNode._parent = nodes[index + 1]; + cycleEdgeNode._parent.uncycle(); + cycleEdgeNode._length = + cycleEdgeNode._parent._length + 1; + } else { + cycleEdgeNode._parent = undefined; + cycleEdgeNode._length = 1; + } + var currentChildLength = cycleEdgeNode._length + 1; + for (var j = i - 2; j >= 0; --j) { + nodes[j]._length = currentChildLength; + currentChildLength++; + } + return; + } + } +}; + +CapturedTrace.prototype.attachExtraTrace = function(error) { + if (error.__stackCleaned__) return; + this.uncycle(); + var parsed = parseStackAndMessage(error); + var message = parsed.message; + var stacks = [parsed.stack]; + + var trace = this; + while (trace !== undefined) { + stacks.push(cleanStack(trace.stack.split("\n"))); + trace = trace._parent; + } + removeCommonRoots(stacks); + removeDuplicateOrEmptyJumps(stacks); + util.notEnumerableProp(error, "stack", reconstructStack(message, stacks)); + util.notEnumerableProp(error, "__stackCleaned__", true); +}; + +var captureStackTrace = (function stackDetection() { + var v8stackFramePattern = /^\s*at\s*/; + var v8stackFormatter = function(stack, error) { + if (typeof stack === "string") return stack; + + if (error.name !== undefined && + error.message !== undefined) { + return error.toString(); + } + return formatNonError(error); + }; + + if (typeof Error.stackTraceLimit === "number" && + typeof Error.captureStackTrace === "function") { + Error.stackTraceLimit += 6; + stackFramePattern = v8stackFramePattern; + formatStack = v8stackFormatter; + var captureStackTrace = Error.captureStackTrace; + + shouldIgnore = function(line) { + return bluebirdFramePattern.test(line); + }; + return function(receiver, ignoreUntil) { + Error.stackTraceLimit += 6; + captureStackTrace(receiver, ignoreUntil); + Error.stackTraceLimit -= 6; + }; + } + var err = new Error(); + + if (typeof err.stack === "string" && + err.stack.split("\n")[0].indexOf("stackDetection@") >= 0) { + stackFramePattern = /@/; + formatStack = v8stackFormatter; + indentStackFrames = true; + return function captureStackTrace(o) { + o.stack = new Error().stack; + }; + } + + var hasStackAfterThrow; + try { throw new Error(); } + catch(e) { + hasStackAfterThrow = ("stack" in e); + } + if (!("stack" in err) && hasStackAfterThrow && + typeof Error.stackTraceLimit === "number") { + stackFramePattern = v8stackFramePattern; + formatStack = v8stackFormatter; + return function captureStackTrace(o) { + Error.stackTraceLimit += 6; + try { throw new Error(); } + catch(e) { o.stack = e.stack; } + Error.stackTraceLimit -= 6; + }; + } + + formatStack = function(stack, error) { + if (typeof stack === "string") return stack; + + if ((typeof error === "object" || + typeof error === "function") && + error.name !== undefined && + error.message !== undefined) { + return error.toString(); + } + return formatNonError(error); + }; + + return null; + +})([]); + +if (typeof console !== "undefined" && typeof console.warn !== "undefined") { + printWarning = function (message) { + console.warn(message); + }; + if (util.isNode && process.stderr.isTTY) { + printWarning = function(message, isSoft) { + var color = isSoft ? "\u001b[33m" : "\u001b[31m"; + console.warn(color + message + "\u001b[0m\n"); + }; + } else if (!util.isNode && typeof (new Error().stack) === "string") { + printWarning = function(message, isSoft) { + console.warn("%c" + message, + isSoft ? "color: darkorange" : "color: red"); + }; + } +} + +var config = { + warnings: warnings, + longStackTraces: false, + cancellation: false, + monitoring: false +}; + +if (longStackTraces) Promise.longStackTraces(); + +return { + longStackTraces: function() { + return config.longStackTraces; + }, + warnings: function() { + return config.warnings; + }, + cancellation: function() { + return config.cancellation; + }, + monitoring: function() { + return config.monitoring; + }, + propagateFromFunction: function() { + return propagateFromFunction; + }, + boundValueFunction: function() { + return boundValueFunction; + }, + checkForgottenReturns: checkForgottenReturns, + setBounds: setBounds, + warn: warn, + deprecated: deprecated, + CapturedTrace: CapturedTrace, + fireDomEvent: fireDomEvent, + fireGlobalEvent: fireGlobalEvent +}; +}; + +},{"./errors":12,"./es5":13,"./util":36}],10:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise) { +function returner() { + return this.value; +} +function thrower() { + throw this.reason; +} + +Promise.prototype["return"] = +Promise.prototype.thenReturn = function (value) { + if (value instanceof Promise) value.suppressUnhandledRejections(); + return this._then( + returner, undefined, undefined, {value: value}, undefined); +}; + +Promise.prototype["throw"] = +Promise.prototype.thenThrow = function (reason) { + return this._then( + thrower, undefined, undefined, {reason: reason}, undefined); +}; + +Promise.prototype.catchThrow = function (reason) { + if (arguments.length <= 1) { + return this._then( + undefined, thrower, undefined, {reason: reason}, undefined); + } else { + var _reason = arguments[1]; + var handler = function() {throw _reason;}; + return this.caught(reason, handler); + } +}; + +Promise.prototype.catchReturn = function (value) { + if (arguments.length <= 1) { + if (value instanceof Promise) value.suppressUnhandledRejections(); + return this._then( + undefined, returner, undefined, {value: value}, undefined); + } else { + var _value = arguments[1]; + if (_value instanceof Promise) _value.suppressUnhandledRejections(); + var handler = function() {return _value;}; + return this.caught(value, handler); + } +}; +}; + +},{}],11:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, INTERNAL) { +var PromiseReduce = Promise.reduce; +var PromiseAll = Promise.all; + +function promiseAllThis() { + return PromiseAll(this); +} + +function PromiseMapSeries(promises, fn) { + return PromiseReduce(promises, fn, INTERNAL, INTERNAL); +} + +Promise.prototype.each = function (fn) { + return PromiseReduce(this, fn, INTERNAL, 0) + ._then(promiseAllThis, undefined, undefined, this, undefined); +}; + +Promise.prototype.mapSeries = function (fn) { + return PromiseReduce(this, fn, INTERNAL, INTERNAL); +}; + +Promise.each = function (promises, fn) { + return PromiseReduce(promises, fn, INTERNAL, 0) + ._then(promiseAllThis, undefined, undefined, promises, undefined); +}; + +Promise.mapSeries = PromiseMapSeries; +}; + + +},{}],12:[function(_dereq_,module,exports){ +"use strict"; +var es5 = _dereq_("./es5"); +var Objectfreeze = es5.freeze; +var util = _dereq_("./util"); +var inherits = util.inherits; +var notEnumerableProp = util.notEnumerableProp; + +function subError(nameProperty, defaultMessage) { + function SubError(message) { + if (!(this instanceof SubError)) return new SubError(message); + notEnumerableProp(this, "message", + typeof message === "string" ? message : defaultMessage); + notEnumerableProp(this, "name", nameProperty); + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } else { + Error.call(this); + } + } + inherits(SubError, Error); + return SubError; +} + +var _TypeError, _RangeError; +var Warning = subError("Warning", "warning"); +var CancellationError = subError("CancellationError", "cancellation error"); +var TimeoutError = subError("TimeoutError", "timeout error"); +var AggregateError = subError("AggregateError", "aggregate error"); +try { + _TypeError = TypeError; + _RangeError = RangeError; +} catch(e) { + _TypeError = subError("TypeError", "type error"); + _RangeError = subError("RangeError", "range error"); +} + +var methods = ("join pop push shift unshift slice filter forEach some " + + "every map indexOf lastIndexOf reduce reduceRight sort reverse").split(" "); + +for (var i = 0; i < methods.length; ++i) { + if (typeof Array.prototype[methods[i]] === "function") { + AggregateError.prototype[methods[i]] = Array.prototype[methods[i]]; + } +} + +es5.defineProperty(AggregateError.prototype, "length", { + value: 0, + configurable: false, + writable: true, + enumerable: true +}); +AggregateError.prototype["isOperational"] = true; +var level = 0; +AggregateError.prototype.toString = function() { + var indent = Array(level * 4 + 1).join(" "); + var ret = "\n" + indent + "AggregateError of:" + "\n"; + level++; + indent = Array(level * 4 + 1).join(" "); + for (var i = 0; i < this.length; ++i) { + var str = this[i] === this ? "[Circular AggregateError]" : this[i] + ""; + var lines = str.split("\n"); + for (var j = 0; j < lines.length; ++j) { + lines[j] = indent + lines[j]; + } + str = lines.join("\n"); + ret += str + "\n"; + } + level--; + return ret; +}; + +function OperationalError(message) { + if (!(this instanceof OperationalError)) + return new OperationalError(message); + notEnumerableProp(this, "name", "OperationalError"); + notEnumerableProp(this, "message", message); + this.cause = message; + this["isOperational"] = true; + + if (message instanceof Error) { + notEnumerableProp(this, "message", message.message); + notEnumerableProp(this, "stack", message.stack); + } else if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + +} +inherits(OperationalError, Error); + +var errorTypes = Error["__BluebirdErrorTypes__"]; +if (!errorTypes) { + errorTypes = Objectfreeze({ + CancellationError: CancellationError, + TimeoutError: TimeoutError, + OperationalError: OperationalError, + RejectionError: OperationalError, + AggregateError: AggregateError + }); + es5.defineProperty(Error, "__BluebirdErrorTypes__", { + value: errorTypes, + writable: false, + enumerable: false, + configurable: false + }); +} + +module.exports = { + Error: Error, + TypeError: _TypeError, + RangeError: _RangeError, + CancellationError: errorTypes.CancellationError, + OperationalError: errorTypes.OperationalError, + TimeoutError: errorTypes.TimeoutError, + AggregateError: errorTypes.AggregateError, + Warning: Warning +}; + +},{"./es5":13,"./util":36}],13:[function(_dereq_,module,exports){ +var isES5 = (function(){ + "use strict"; + return this === undefined; +})(); + +if (isES5) { + module.exports = { + freeze: Object.freeze, + defineProperty: Object.defineProperty, + getDescriptor: Object.getOwnPropertyDescriptor, + keys: Object.keys, + names: Object.getOwnPropertyNames, + getPrototypeOf: Object.getPrototypeOf, + isArray: Array.isArray, + isES5: isES5, + propertyIsWritable: function(obj, prop) { + var descriptor = Object.getOwnPropertyDescriptor(obj, prop); + return !!(!descriptor || descriptor.writable || descriptor.set); + } + }; +} else { + var has = {}.hasOwnProperty; + var str = {}.toString; + var proto = {}.constructor.prototype; + + var ObjectKeys = function (o) { + var ret = []; + for (var key in o) { + if (has.call(o, key)) { + ret.push(key); + } + } + return ret; + }; + + var ObjectGetDescriptor = function(o, key) { + return {value: o[key]}; + }; + + var ObjectDefineProperty = function (o, key, desc) { + o[key] = desc.value; + return o; + }; + + var ObjectFreeze = function (obj) { + return obj; + }; + + var ObjectGetPrototypeOf = function (obj) { + try { + return Object(obj).constructor.prototype; + } + catch (e) { + return proto; + } + }; + + var ArrayIsArray = function (obj) { + try { + return str.call(obj) === "[object Array]"; + } + catch(e) { + return false; + } + }; + + module.exports = { + isArray: ArrayIsArray, + keys: ObjectKeys, + names: ObjectKeys, + defineProperty: ObjectDefineProperty, + getDescriptor: ObjectGetDescriptor, + freeze: ObjectFreeze, + getPrototypeOf: ObjectGetPrototypeOf, + isES5: isES5, + propertyIsWritable: function() { + return true; + } + }; +} + +},{}],14:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, INTERNAL) { +var PromiseMap = Promise.map; + +Promise.prototype.filter = function (fn, options) { + return PromiseMap(this, fn, options, INTERNAL); +}; + +Promise.filter = function (promises, fn, options) { + return PromiseMap(promises, fn, options, INTERNAL); +}; +}; + +},{}],15:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, tryConvertToPromise, NEXT_FILTER) { +var util = _dereq_("./util"); +var CancellationError = Promise.CancellationError; +var errorObj = util.errorObj; +var catchFilter = _dereq_("./catch_filter")(NEXT_FILTER); + +function PassThroughHandlerContext(promise, type, handler) { + this.promise = promise; + this.type = type; + this.handler = handler; + this.called = false; + this.cancelPromise = null; +} + +PassThroughHandlerContext.prototype.isFinallyHandler = function() { + return this.type === 0; +}; + +function FinallyHandlerCancelReaction(finallyHandler) { + this.finallyHandler = finallyHandler; +} + +FinallyHandlerCancelReaction.prototype._resultCancelled = function() { + checkCancel(this.finallyHandler); +}; + +function checkCancel(ctx, reason) { + if (ctx.cancelPromise != null) { + if (arguments.length > 1) { + ctx.cancelPromise._reject(reason); + } else { + ctx.cancelPromise._cancel(); + } + ctx.cancelPromise = null; + return true; + } + return false; +} + +function succeed() { + return finallyHandler.call(this, this.promise._target()._settledValue()); +} +function fail(reason) { + if (checkCancel(this, reason)) return; + errorObj.e = reason; + return errorObj; +} +function finallyHandler(reasonOrValue) { + var promise = this.promise; + var handler = this.handler; + + if (!this.called) { + this.called = true; + var ret = this.isFinallyHandler() + ? handler.call(promise._boundValue()) + : handler.call(promise._boundValue(), reasonOrValue); + if (ret === NEXT_FILTER) { + return ret; + } else if (ret !== undefined) { + promise._setReturnedNonUndefined(); + var maybePromise = tryConvertToPromise(ret, promise); + if (maybePromise instanceof Promise) { + if (this.cancelPromise != null) { + if (maybePromise._isCancelled()) { + var reason = + new CancellationError("late cancellation observer"); + promise._attachExtraTrace(reason); + errorObj.e = reason; + return errorObj; + } else if (maybePromise.isPending()) { + maybePromise._attachCancellationCallback( + new FinallyHandlerCancelReaction(this)); + } + } + return maybePromise._then( + succeed, fail, undefined, this, undefined); + } + } + } + + if (promise.isRejected()) { + checkCancel(this); + errorObj.e = reasonOrValue; + return errorObj; + } else { + checkCancel(this); + return reasonOrValue; + } +} + +Promise.prototype._passThrough = function(handler, type, success, fail) { + if (typeof handler !== "function") return this.then(); + return this._then(success, + fail, + undefined, + new PassThroughHandlerContext(this, type, handler), + undefined); +}; + +Promise.prototype.lastly = +Promise.prototype["finally"] = function (handler) { + return this._passThrough(handler, + 0, + finallyHandler, + finallyHandler); +}; + + +Promise.prototype.tap = function (handler) { + return this._passThrough(handler, 1, finallyHandler); +}; + +Promise.prototype.tapCatch = function (handlerOrPredicate) { + var len = arguments.length; + if(len === 1) { + return this._passThrough(handlerOrPredicate, + 1, + undefined, + finallyHandler); + } else { + var catchInstances = new Array(len - 1), + j = 0, i; + for (i = 0; i < len - 1; ++i) { + var item = arguments[i]; + if (util.isObject(item)) { + catchInstances[j++] = item; + } else { + return Promise.reject(new TypeError( + "tapCatch statement predicate: " + + "expecting an object but got " + util.classString(item) + )); + } + } + catchInstances.length = j; + var handler = arguments[i]; + return this._passThrough(catchFilter(catchInstances, handler, this), + 1, + undefined, + finallyHandler); + } + +}; + +return PassThroughHandlerContext; +}; + +},{"./catch_filter":7,"./util":36}],16:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, + apiRejection, + INTERNAL, + tryConvertToPromise, + Proxyable, + debug) { +var errors = _dereq_("./errors"); +var TypeError = errors.TypeError; +var util = _dereq_("./util"); +var errorObj = util.errorObj; +var tryCatch = util.tryCatch; +var yieldHandlers = []; + +function promiseFromYieldHandler(value, yieldHandlers, traceParent) { + for (var i = 0; i < yieldHandlers.length; ++i) { + traceParent._pushContext(); + var result = tryCatch(yieldHandlers[i])(value); + traceParent._popContext(); + if (result === errorObj) { + traceParent._pushContext(); + var ret = Promise.reject(errorObj.e); + traceParent._popContext(); + return ret; + } + var maybePromise = tryConvertToPromise(result, traceParent); + if (maybePromise instanceof Promise) return maybePromise; + } + return null; +} + +function PromiseSpawn(generatorFunction, receiver, yieldHandler, stack) { + if (debug.cancellation()) { + var internal = new Promise(INTERNAL); + var _finallyPromise = this._finallyPromise = new Promise(INTERNAL); + this._promise = internal.lastly(function() { + return _finallyPromise; + }); + internal._captureStackTrace(); + internal._setOnCancel(this); + } else { + var promise = this._promise = new Promise(INTERNAL); + promise._captureStackTrace(); + } + this._stack = stack; + this._generatorFunction = generatorFunction; + this._receiver = receiver; + this._generator = undefined; + this._yieldHandlers = typeof yieldHandler === "function" + ? [yieldHandler].concat(yieldHandlers) + : yieldHandlers; + this._yieldedPromise = null; + this._cancellationPhase = false; +} +util.inherits(PromiseSpawn, Proxyable); + +PromiseSpawn.prototype._isResolved = function() { + return this._promise === null; +}; + +PromiseSpawn.prototype._cleanup = function() { + this._promise = this._generator = null; + if (debug.cancellation() && this._finallyPromise !== null) { + this._finallyPromise._fulfill(); + this._finallyPromise = null; + } +}; + +PromiseSpawn.prototype._promiseCancelled = function() { + if (this._isResolved()) return; + var implementsReturn = typeof this._generator["return"] !== "undefined"; + + var result; + if (!implementsReturn) { + var reason = new Promise.CancellationError( + "generator .return() sentinel"); + Promise.coroutine.returnSentinel = reason; + this._promise._attachExtraTrace(reason); + this._promise._pushContext(); + result = tryCatch(this._generator["throw"]).call(this._generator, + reason); + this._promise._popContext(); + } else { + this._promise._pushContext(); + result = tryCatch(this._generator["return"]).call(this._generator, + undefined); + this._promise._popContext(); + } + this._cancellationPhase = true; + this._yieldedPromise = null; + this._continue(result); +}; + +PromiseSpawn.prototype._promiseFulfilled = function(value) { + this._yieldedPromise = null; + this._promise._pushContext(); + var result = tryCatch(this._generator.next).call(this._generator, value); + this._promise._popContext(); + this._continue(result); +}; + +PromiseSpawn.prototype._promiseRejected = function(reason) { + this._yieldedPromise = null; + this._promise._attachExtraTrace(reason); + this._promise._pushContext(); + var result = tryCatch(this._generator["throw"]) + .call(this._generator, reason); + this._promise._popContext(); + this._continue(result); +}; + +PromiseSpawn.prototype._resultCancelled = function() { + if (this._yieldedPromise instanceof Promise) { + var promise = this._yieldedPromise; + this._yieldedPromise = null; + promise.cancel(); + } +}; + +PromiseSpawn.prototype.promise = function () { + return this._promise; +}; + +PromiseSpawn.prototype._run = function () { + this._generator = this._generatorFunction.call(this._receiver); + this._receiver = + this._generatorFunction = undefined; + this._promiseFulfilled(undefined); +}; + +PromiseSpawn.prototype._continue = function (result) { + var promise = this._promise; + if (result === errorObj) { + this._cleanup(); + if (this._cancellationPhase) { + return promise.cancel(); + } else { + return promise._rejectCallback(result.e, false); + } + } + + var value = result.value; + if (result.done === true) { + this._cleanup(); + if (this._cancellationPhase) { + return promise.cancel(); + } else { + return promise._resolveCallback(value); + } + } else { + var maybePromise = tryConvertToPromise(value, this._promise); + if (!(maybePromise instanceof Promise)) { + maybePromise = + promiseFromYieldHandler(maybePromise, + this._yieldHandlers, + this._promise); + if (maybePromise === null) { + this._promiseRejected( + new TypeError( + "A value %s was yielded that could not be treated as a promise\u000a\u000a See http://goo.gl/MqrFmX\u000a\u000a".replace("%s", String(value)) + + "From coroutine:\u000a" + + this._stack.split("\n").slice(1, -7).join("\n") + ) + ); + return; + } + } + maybePromise = maybePromise._target(); + var bitField = maybePromise._bitField; + ; + if (((bitField & 50397184) === 0)) { + this._yieldedPromise = maybePromise; + maybePromise._proxy(this, null); + } else if (((bitField & 33554432) !== 0)) { + Promise._async.invoke( + this._promiseFulfilled, this, maybePromise._value() + ); + } else if (((bitField & 16777216) !== 0)) { + Promise._async.invoke( + this._promiseRejected, this, maybePromise._reason() + ); + } else { + this._promiseCancelled(); + } + } +}; + +Promise.coroutine = function (generatorFunction, options) { + if (typeof generatorFunction !== "function") { + throw new TypeError("generatorFunction must be a function\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + var yieldHandler = Object(options).yieldHandler; + var PromiseSpawn$ = PromiseSpawn; + var stack = new Error().stack; + return function () { + var generator = generatorFunction.apply(this, arguments); + var spawn = new PromiseSpawn$(undefined, undefined, yieldHandler, + stack); + var ret = spawn.promise(); + spawn._generator = generator; + spawn._promiseFulfilled(undefined); + return ret; + }; +}; + +Promise.coroutine.addYieldHandler = function(fn) { + if (typeof fn !== "function") { + throw new TypeError("expecting a function but got " + util.classString(fn)); + } + yieldHandlers.push(fn); +}; + +Promise.spawn = function (generatorFunction) { + debug.deprecated("Promise.spawn()", "Promise.coroutine()"); + if (typeof generatorFunction !== "function") { + return apiRejection("generatorFunction must be a function\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + var spawn = new PromiseSpawn(generatorFunction, this); + var ret = spawn.promise(); + spawn._run(Promise.spawn); + return ret; +}; +}; + +},{"./errors":12,"./util":36}],17:[function(_dereq_,module,exports){ +"use strict"; +module.exports = +function(Promise, PromiseArray, tryConvertToPromise, INTERNAL, async, + getDomain) { +var util = _dereq_("./util"); +var canEvaluate = util.canEvaluate; +var tryCatch = util.tryCatch; +var errorObj = util.errorObj; +var reject; + +if (!true) { +if (canEvaluate) { + var thenCallback = function(i) { + return new Function("value", "holder", " \n\ + 'use strict'; \n\ + holder.pIndex = value; \n\ + holder.checkFulfillment(this); \n\ + ".replace(/Index/g, i)); + }; + + var promiseSetter = function(i) { + return new Function("promise", "holder", " \n\ + 'use strict'; \n\ + holder.pIndex = promise; \n\ + ".replace(/Index/g, i)); + }; + + var generateHolderClass = function(total) { + var props = new Array(total); + for (var i = 0; i < props.length; ++i) { + props[i] = "this.p" + (i+1); + } + var assignment = props.join(" = ") + " = null;"; + var cancellationCode= "var promise;\n" + props.map(function(prop) { + return " \n\ + promise = " + prop + "; \n\ + if (promise instanceof Promise) { \n\ + promise.cancel(); \n\ + } \n\ + "; + }).join("\n"); + var passedArguments = props.join(", "); + var name = "Holder$" + total; + + + var code = "return function(tryCatch, errorObj, Promise, async) { \n\ + 'use strict'; \n\ + function [TheName](fn) { \n\ + [TheProperties] \n\ + this.fn = fn; \n\ + this.asyncNeeded = true; \n\ + this.now = 0; \n\ + } \n\ + \n\ + [TheName].prototype._callFunction = function(promise) { \n\ + promise._pushContext(); \n\ + var ret = tryCatch(this.fn)([ThePassedArguments]); \n\ + promise._popContext(); \n\ + if (ret === errorObj) { \n\ + promise._rejectCallback(ret.e, false); \n\ + } else { \n\ + promise._resolveCallback(ret); \n\ + } \n\ + }; \n\ + \n\ + [TheName].prototype.checkFulfillment = function(promise) { \n\ + var now = ++this.now; \n\ + if (now === [TheTotal]) { \n\ + if (this.asyncNeeded) { \n\ + async.invoke(this._callFunction, this, promise); \n\ + } else { \n\ + this._callFunction(promise); \n\ + } \n\ + \n\ + } \n\ + }; \n\ + \n\ + [TheName].prototype._resultCancelled = function() { \n\ + [CancellationCode] \n\ + }; \n\ + \n\ + return [TheName]; \n\ + }(tryCatch, errorObj, Promise, async); \n\ + "; + + code = code.replace(/\[TheName\]/g, name) + .replace(/\[TheTotal\]/g, total) + .replace(/\[ThePassedArguments\]/g, passedArguments) + .replace(/\[TheProperties\]/g, assignment) + .replace(/\[CancellationCode\]/g, cancellationCode); + + return new Function("tryCatch", "errorObj", "Promise", "async", code) + (tryCatch, errorObj, Promise, async); + }; + + var holderClasses = []; + var thenCallbacks = []; + var promiseSetters = []; + + for (var i = 0; i < 8; ++i) { + holderClasses.push(generateHolderClass(i + 1)); + thenCallbacks.push(thenCallback(i + 1)); + promiseSetters.push(promiseSetter(i + 1)); + } + + reject = function (reason) { + this._reject(reason); + }; +}} + +Promise.join = function () { + var last = arguments.length - 1; + var fn; + if (last > 0 && typeof arguments[last] === "function") { + fn = arguments[last]; + if (!true) { + if (last <= 8 && canEvaluate) { + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + var HolderClass = holderClasses[last - 1]; + var holder = new HolderClass(fn); + var callbacks = thenCallbacks; + + for (var i = 0; i < last; ++i) { + var maybePromise = tryConvertToPromise(arguments[i], ret); + if (maybePromise instanceof Promise) { + maybePromise = maybePromise._target(); + var bitField = maybePromise._bitField; + ; + if (((bitField & 50397184) === 0)) { + maybePromise._then(callbacks[i], reject, + undefined, ret, holder); + promiseSetters[i](maybePromise, holder); + holder.asyncNeeded = false; + } else if (((bitField & 33554432) !== 0)) { + callbacks[i].call(ret, + maybePromise._value(), holder); + } else if (((bitField & 16777216) !== 0)) { + ret._reject(maybePromise._reason()); + } else { + ret._cancel(); + } + } else { + callbacks[i].call(ret, maybePromise, holder); + } + } + + if (!ret._isFateSealed()) { + if (holder.asyncNeeded) { + var domain = getDomain(); + if (domain !== null) { + holder.fn = util.domainBind(domain, holder.fn); + } + } + ret._setAsyncGuaranteed(); + ret._setOnCancel(holder); + } + return ret; + } + } + } + var args = [].slice.call(arguments);; + if (fn) args.pop(); + var ret = new PromiseArray(args).promise(); + return fn !== undefined ? ret.spread(fn) : ret; +}; + +}; + +},{"./util":36}],18:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, + PromiseArray, + apiRejection, + tryConvertToPromise, + INTERNAL, + debug) { +var getDomain = Promise._getDomain; +var util = _dereq_("./util"); +var tryCatch = util.tryCatch; +var errorObj = util.errorObj; +var async = Promise._async; + +function MappingPromiseArray(promises, fn, limit, _filter) { + this.constructor$(promises); + this._promise._captureStackTrace(); + var domain = getDomain(); + this._callback = domain === null ? fn : util.domainBind(domain, fn); + this._preservedValues = _filter === INTERNAL + ? new Array(this.length()) + : null; + this._limit = limit; + this._inFlight = 0; + this._queue = []; + async.invoke(this._asyncInit, this, undefined); +} +util.inherits(MappingPromiseArray, PromiseArray); + +MappingPromiseArray.prototype._asyncInit = function() { + this._init$(undefined, -2); +}; + +MappingPromiseArray.prototype._init = function () {}; + +MappingPromiseArray.prototype._promiseFulfilled = function (value, index) { + var values = this._values; + var length = this.length(); + var preservedValues = this._preservedValues; + var limit = this._limit; + + if (index < 0) { + index = (index * -1) - 1; + values[index] = value; + if (limit >= 1) { + this._inFlight--; + this._drainQueue(); + if (this._isResolved()) return true; + } + } else { + if (limit >= 1 && this._inFlight >= limit) { + values[index] = value; + this._queue.push(index); + return false; + } + if (preservedValues !== null) preservedValues[index] = value; + + var promise = this._promise; + var callback = this._callback; + var receiver = promise._boundValue(); + promise._pushContext(); + var ret = tryCatch(callback).call(receiver, value, index, length); + var promiseCreated = promise._popContext(); + debug.checkForgottenReturns( + ret, + promiseCreated, + preservedValues !== null ? "Promise.filter" : "Promise.map", + promise + ); + if (ret === errorObj) { + this._reject(ret.e); + return true; + } + + var maybePromise = tryConvertToPromise(ret, this._promise); + if (maybePromise instanceof Promise) { + maybePromise = maybePromise._target(); + var bitField = maybePromise._bitField; + ; + if (((bitField & 50397184) === 0)) { + if (limit >= 1) this._inFlight++; + values[index] = maybePromise; + maybePromise._proxy(this, (index + 1) * -1); + return false; + } else if (((bitField & 33554432) !== 0)) { + ret = maybePromise._value(); + } else if (((bitField & 16777216) !== 0)) { + this._reject(maybePromise._reason()); + return true; + } else { + this._cancel(); + return true; + } + } + values[index] = ret; + } + var totalResolved = ++this._totalResolved; + if (totalResolved >= length) { + if (preservedValues !== null) { + this._filter(values, preservedValues); + } else { + this._resolve(values); + } + return true; + } + return false; +}; + +MappingPromiseArray.prototype._drainQueue = function () { + var queue = this._queue; + var limit = this._limit; + var values = this._values; + while (queue.length > 0 && this._inFlight < limit) { + if (this._isResolved()) return; + var index = queue.pop(); + this._promiseFulfilled(values[index], index); + } +}; + +MappingPromiseArray.prototype._filter = function (booleans, values) { + var len = values.length; + var ret = new Array(len); + var j = 0; + for (var i = 0; i < len; ++i) { + if (booleans[i]) ret[j++] = values[i]; + } + ret.length = j; + this._resolve(ret); +}; + +MappingPromiseArray.prototype.preservedValues = function () { + return this._preservedValues; +}; + +function map(promises, fn, options, _filter) { + if (typeof fn !== "function") { + return apiRejection("expecting a function but got " + util.classString(fn)); + } + + var limit = 0; + if (options !== undefined) { + if (typeof options === "object" && options !== null) { + if (typeof options.concurrency !== "number") { + return Promise.reject( + new TypeError("'concurrency' must be a number but it is " + + util.classString(options.concurrency))); + } + limit = options.concurrency; + } else { + return Promise.reject(new TypeError( + "options argument must be an object but it is " + + util.classString(options))); + } + } + limit = typeof limit === "number" && + isFinite(limit) && limit >= 1 ? limit : 0; + return new MappingPromiseArray(promises, fn, limit, _filter).promise(); +} + +Promise.prototype.map = function (fn, options) { + return map(this, fn, options, null); +}; + +Promise.map = function (promises, fn, options, _filter) { + return map(promises, fn, options, _filter); +}; + + +}; + +},{"./util":36}],19:[function(_dereq_,module,exports){ +"use strict"; +module.exports = +function(Promise, INTERNAL, tryConvertToPromise, apiRejection, debug) { +var util = _dereq_("./util"); +var tryCatch = util.tryCatch; + +Promise.method = function (fn) { + if (typeof fn !== "function") { + throw new Promise.TypeError("expecting a function but got " + util.classString(fn)); + } + return function () { + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + ret._pushContext(); + var value = tryCatch(fn).apply(this, arguments); + var promiseCreated = ret._popContext(); + debug.checkForgottenReturns( + value, promiseCreated, "Promise.method", ret); + ret._resolveFromSyncValue(value); + return ret; + }; +}; + +Promise.attempt = Promise["try"] = function (fn) { + if (typeof fn !== "function") { + return apiRejection("expecting a function but got " + util.classString(fn)); + } + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + ret._pushContext(); + var value; + if (arguments.length > 1) { + debug.deprecated("calling Promise.try with more than 1 argument"); + var arg = arguments[1]; + var ctx = arguments[2]; + value = util.isArray(arg) ? tryCatch(fn).apply(ctx, arg) + : tryCatch(fn).call(ctx, arg); + } else { + value = tryCatch(fn)(); + } + var promiseCreated = ret._popContext(); + debug.checkForgottenReturns( + value, promiseCreated, "Promise.try", ret); + ret._resolveFromSyncValue(value); + return ret; +}; + +Promise.prototype._resolveFromSyncValue = function (value) { + if (value === util.errorObj) { + this._rejectCallback(value.e, false); + } else { + this._resolveCallback(value, true); + } +}; +}; + +},{"./util":36}],20:[function(_dereq_,module,exports){ +"use strict"; +var util = _dereq_("./util"); +var maybeWrapAsError = util.maybeWrapAsError; +var errors = _dereq_("./errors"); +var OperationalError = errors.OperationalError; +var es5 = _dereq_("./es5"); + +function isUntypedError(obj) { + return obj instanceof Error && + es5.getPrototypeOf(obj) === Error.prototype; +} + +var rErrorKey = /^(?:name|message|stack|cause)$/; +function wrapAsOperationalError(obj) { + var ret; + if (isUntypedError(obj)) { + ret = new OperationalError(obj); + ret.name = obj.name; + ret.message = obj.message; + ret.stack = obj.stack; + var keys = es5.keys(obj); + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (!rErrorKey.test(key)) { + ret[key] = obj[key]; + } + } + return ret; + } + util.markAsOriginatingFromRejection(obj); + return obj; +} + +function nodebackForPromise(promise, multiArgs) { + return function(err, value) { + if (promise === null) return; + if (err) { + var wrapped = wrapAsOperationalError(maybeWrapAsError(err)); + promise._attachExtraTrace(wrapped); + promise._reject(wrapped); + } else if (!multiArgs) { + promise._fulfill(value); + } else { + var args = [].slice.call(arguments, 1);; + promise._fulfill(args); + } + promise = null; + }; +} + +module.exports = nodebackForPromise; + +},{"./errors":12,"./es5":13,"./util":36}],21:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise) { +var util = _dereq_("./util"); +var async = Promise._async; +var tryCatch = util.tryCatch; +var errorObj = util.errorObj; + +function spreadAdapter(val, nodeback) { + var promise = this; + if (!util.isArray(val)) return successAdapter.call(promise, val, nodeback); + var ret = + tryCatch(nodeback).apply(promise._boundValue(), [null].concat(val)); + if (ret === errorObj) { + async.throwLater(ret.e); + } +} + +function successAdapter(val, nodeback) { + var promise = this; + var receiver = promise._boundValue(); + var ret = val === undefined + ? tryCatch(nodeback).call(receiver, null) + : tryCatch(nodeback).call(receiver, null, val); + if (ret === errorObj) { + async.throwLater(ret.e); + } +} +function errorAdapter(reason, nodeback) { + var promise = this; + if (!reason) { + var newReason = new Error(reason + ""); + newReason.cause = reason; + reason = newReason; + } + var ret = tryCatch(nodeback).call(promise._boundValue(), reason); + if (ret === errorObj) { + async.throwLater(ret.e); + } +} + +Promise.prototype.asCallback = Promise.prototype.nodeify = function (nodeback, + options) { + if (typeof nodeback == "function") { + var adapter = successAdapter; + if (options !== undefined && Object(options).spread) { + adapter = spreadAdapter; + } + this._then( + adapter, + errorAdapter, + undefined, + this, + nodeback + ); + } + return this; +}; +}; + +},{"./util":36}],22:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function() { +var makeSelfResolutionError = function () { + return new TypeError("circular promise resolution chain\u000a\u000a See http://goo.gl/MqrFmX\u000a"); +}; +var reflectHandler = function() { + return new Promise.PromiseInspection(this._target()); +}; +var apiRejection = function(msg) { + return Promise.reject(new TypeError(msg)); +}; +function Proxyable() {} +var UNDEFINED_BINDING = {}; +var util = _dereq_("./util"); + +var getDomain; +if (util.isNode) { + getDomain = function() { + var ret = process.domain; + if (ret === undefined) ret = null; + return ret; + }; +} else { + getDomain = function() { + return null; + }; +} +util.notEnumerableProp(Promise, "_getDomain", getDomain); + +var es5 = _dereq_("./es5"); +var Async = _dereq_("./async"); +var async = new Async(); +es5.defineProperty(Promise, "_async", {value: async}); +var errors = _dereq_("./errors"); +var TypeError = Promise.TypeError = errors.TypeError; +Promise.RangeError = errors.RangeError; +var CancellationError = Promise.CancellationError = errors.CancellationError; +Promise.TimeoutError = errors.TimeoutError; +Promise.OperationalError = errors.OperationalError; +Promise.RejectionError = errors.OperationalError; +Promise.AggregateError = errors.AggregateError; +var INTERNAL = function(){}; +var APPLY = {}; +var NEXT_FILTER = {}; +var tryConvertToPromise = _dereq_("./thenables")(Promise, INTERNAL); +var PromiseArray = + _dereq_("./promise_array")(Promise, INTERNAL, + tryConvertToPromise, apiRejection, Proxyable); +var Context = _dereq_("./context")(Promise); + /*jshint unused:false*/ +var createContext = Context.create; +var debug = _dereq_("./debuggability")(Promise, Context); +var CapturedTrace = debug.CapturedTrace; +var PassThroughHandlerContext = + _dereq_("./finally")(Promise, tryConvertToPromise, NEXT_FILTER); +var catchFilter = _dereq_("./catch_filter")(NEXT_FILTER); +var nodebackForPromise = _dereq_("./nodeback"); +var errorObj = util.errorObj; +var tryCatch = util.tryCatch; +function check(self, executor) { + if (self == null || self.constructor !== Promise) { + throw new TypeError("the promise constructor cannot be invoked directly\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + if (typeof executor !== "function") { + throw new TypeError("expecting a function but got " + util.classString(executor)); + } + +} + +function Promise(executor) { + if (executor !== INTERNAL) { + check(this, executor); + } + this._bitField = 0; + this._fulfillmentHandler0 = undefined; + this._rejectionHandler0 = undefined; + this._promise0 = undefined; + this._receiver0 = undefined; + this._resolveFromExecutor(executor); + this._promiseCreated(); + this._fireEvent("promiseCreated", this); +} + +Promise.prototype.toString = function () { + return "[object Promise]"; +}; + +Promise.prototype.caught = Promise.prototype["catch"] = function (fn) { + var len = arguments.length; + if (len > 1) { + var catchInstances = new Array(len - 1), + j = 0, i; + for (i = 0; i < len - 1; ++i) { + var item = arguments[i]; + if (util.isObject(item)) { + catchInstances[j++] = item; + } else { + return apiRejection("Catch statement predicate: " + + "expecting an object but got " + util.classString(item)); + } + } + catchInstances.length = j; + fn = arguments[i]; + return this.then(undefined, catchFilter(catchInstances, fn, this)); + } + return this.then(undefined, fn); +}; + +Promise.prototype.reflect = function () { + return this._then(reflectHandler, + reflectHandler, undefined, this, undefined); +}; + +Promise.prototype.then = function (didFulfill, didReject) { + if (debug.warnings() && arguments.length > 0 && + typeof didFulfill !== "function" && + typeof didReject !== "function") { + var msg = ".then() only accepts functions but was passed: " + + util.classString(didFulfill); + if (arguments.length > 1) { + msg += ", " + util.classString(didReject); + } + this._warn(msg); + } + return this._then(didFulfill, didReject, undefined, undefined, undefined); +}; + +Promise.prototype.done = function (didFulfill, didReject) { + var promise = + this._then(didFulfill, didReject, undefined, undefined, undefined); + promise._setIsFinal(); +}; + +Promise.prototype.spread = function (fn) { + if (typeof fn !== "function") { + return apiRejection("expecting a function but got " + util.classString(fn)); + } + return this.all()._then(fn, undefined, undefined, APPLY, undefined); +}; + +Promise.prototype.toJSON = function () { + var ret = { + isFulfilled: false, + isRejected: false, + fulfillmentValue: undefined, + rejectionReason: undefined + }; + if (this.isFulfilled()) { + ret.fulfillmentValue = this.value(); + ret.isFulfilled = true; + } else if (this.isRejected()) { + ret.rejectionReason = this.reason(); + ret.isRejected = true; + } + return ret; +}; + +Promise.prototype.all = function () { + if (arguments.length > 0) { + this._warn(".all() was passed arguments but it does not take any"); + } + return new PromiseArray(this).promise(); +}; + +Promise.prototype.error = function (fn) { + return this.caught(util.originatesFromRejection, fn); +}; + +Promise.getNewLibraryCopy = module.exports; + +Promise.is = function (val) { + return val instanceof Promise; +}; + +Promise.fromNode = Promise.fromCallback = function(fn) { + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + var multiArgs = arguments.length > 1 ? !!Object(arguments[1]).multiArgs + : false; + var result = tryCatch(fn)(nodebackForPromise(ret, multiArgs)); + if (result === errorObj) { + ret._rejectCallback(result.e, true); + } + if (!ret._isFateSealed()) ret._setAsyncGuaranteed(); + return ret; +}; + +Promise.all = function (promises) { + return new PromiseArray(promises).promise(); +}; + +Promise.cast = function (obj) { + var ret = tryConvertToPromise(obj); + if (!(ret instanceof Promise)) { + ret = new Promise(INTERNAL); + ret._captureStackTrace(); + ret._setFulfilled(); + ret._rejectionHandler0 = obj; + } + return ret; +}; + +Promise.resolve = Promise.fulfilled = Promise.cast; + +Promise.reject = Promise.rejected = function (reason) { + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + ret._rejectCallback(reason, true); + return ret; +}; + +Promise.setScheduler = function(fn) { + if (typeof fn !== "function") { + throw new TypeError("expecting a function but got " + util.classString(fn)); + } + return async.setScheduler(fn); +}; + +Promise.prototype._then = function ( + didFulfill, + didReject, + _, receiver, + internalData +) { + var haveInternalData = internalData !== undefined; + var promise = haveInternalData ? internalData : new Promise(INTERNAL); + var target = this._target(); + var bitField = target._bitField; + + if (!haveInternalData) { + promise._propagateFrom(this, 3); + promise._captureStackTrace(); + if (receiver === undefined && + ((this._bitField & 2097152) !== 0)) { + if (!((bitField & 50397184) === 0)) { + receiver = this._boundValue(); + } else { + receiver = target === this ? undefined : this._boundTo; + } + } + this._fireEvent("promiseChained", this, promise); + } + + var domain = getDomain(); + if (!((bitField & 50397184) === 0)) { + var handler, value, settler = target._settlePromiseCtx; + if (((bitField & 33554432) !== 0)) { + value = target._rejectionHandler0; + handler = didFulfill; + } else if (((bitField & 16777216) !== 0)) { + value = target._fulfillmentHandler0; + handler = didReject; + target._unsetRejectionIsUnhandled(); + } else { + settler = target._settlePromiseLateCancellationObserver; + value = new CancellationError("late cancellation observer"); + target._attachExtraTrace(value); + handler = didReject; + } + + async.invoke(settler, target, { + handler: domain === null ? handler + : (typeof handler === "function" && + util.domainBind(domain, handler)), + promise: promise, + receiver: receiver, + value: value + }); + } else { + target._addCallbacks(didFulfill, didReject, promise, receiver, domain); + } + + return promise; +}; + +Promise.prototype._length = function () { + return this._bitField & 65535; +}; + +Promise.prototype._isFateSealed = function () { + return (this._bitField & 117506048) !== 0; +}; + +Promise.prototype._isFollowing = function () { + return (this._bitField & 67108864) === 67108864; +}; + +Promise.prototype._setLength = function (len) { + this._bitField = (this._bitField & -65536) | + (len & 65535); +}; + +Promise.prototype._setFulfilled = function () { + this._bitField = this._bitField | 33554432; + this._fireEvent("promiseFulfilled", this); +}; + +Promise.prototype._setRejected = function () { + this._bitField = this._bitField | 16777216; + this._fireEvent("promiseRejected", this); +}; + +Promise.prototype._setFollowing = function () { + this._bitField = this._bitField | 67108864; + this._fireEvent("promiseResolved", this); +}; + +Promise.prototype._setIsFinal = function () { + this._bitField = this._bitField | 4194304; +}; + +Promise.prototype._isFinal = function () { + return (this._bitField & 4194304) > 0; +}; + +Promise.prototype._unsetCancelled = function() { + this._bitField = this._bitField & (~65536); +}; + +Promise.prototype._setCancelled = function() { + this._bitField = this._bitField | 65536; + this._fireEvent("promiseCancelled", this); +}; + +Promise.prototype._setWillBeCancelled = function() { + this._bitField = this._bitField | 8388608; +}; + +Promise.prototype._setAsyncGuaranteed = function() { + if (async.hasCustomScheduler()) return; + this._bitField = this._bitField | 134217728; +}; + +Promise.prototype._receiverAt = function (index) { + var ret = index === 0 ? this._receiver0 : this[ + index * 4 - 4 + 3]; + if (ret === UNDEFINED_BINDING) { + return undefined; + } else if (ret === undefined && this._isBound()) { + return this._boundValue(); + } + return ret; +}; + +Promise.prototype._promiseAt = function (index) { + return this[ + index * 4 - 4 + 2]; +}; + +Promise.prototype._fulfillmentHandlerAt = function (index) { + return this[ + index * 4 - 4 + 0]; +}; + +Promise.prototype._rejectionHandlerAt = function (index) { + return this[ + index * 4 - 4 + 1]; +}; + +Promise.prototype._boundValue = function() {}; + +Promise.prototype._migrateCallback0 = function (follower) { + var bitField = follower._bitField; + var fulfill = follower._fulfillmentHandler0; + var reject = follower._rejectionHandler0; + var promise = follower._promise0; + var receiver = follower._receiverAt(0); + if (receiver === undefined) receiver = UNDEFINED_BINDING; + this._addCallbacks(fulfill, reject, promise, receiver, null); +}; + +Promise.prototype._migrateCallbackAt = function (follower, index) { + var fulfill = follower._fulfillmentHandlerAt(index); + var reject = follower._rejectionHandlerAt(index); + var promise = follower._promiseAt(index); + var receiver = follower._receiverAt(index); + if (receiver === undefined) receiver = UNDEFINED_BINDING; + this._addCallbacks(fulfill, reject, promise, receiver, null); +}; + +Promise.prototype._addCallbacks = function ( + fulfill, + reject, + promise, + receiver, + domain +) { + var index = this._length(); + + if (index >= 65535 - 4) { + index = 0; + this._setLength(0); + } + + if (index === 0) { + this._promise0 = promise; + this._receiver0 = receiver; + if (typeof fulfill === "function") { + this._fulfillmentHandler0 = + domain === null ? fulfill : util.domainBind(domain, fulfill); + } + if (typeof reject === "function") { + this._rejectionHandler0 = + domain === null ? reject : util.domainBind(domain, reject); + } + } else { + var base = index * 4 - 4; + this[base + 2] = promise; + this[base + 3] = receiver; + if (typeof fulfill === "function") { + this[base + 0] = + domain === null ? fulfill : util.domainBind(domain, fulfill); + } + if (typeof reject === "function") { + this[base + 1] = + domain === null ? reject : util.domainBind(domain, reject); + } + } + this._setLength(index + 1); + return index; +}; + +Promise.prototype._proxy = function (proxyable, arg) { + this._addCallbacks(undefined, undefined, arg, proxyable, null); +}; + +Promise.prototype._resolveCallback = function(value, shouldBind) { + if (((this._bitField & 117506048) !== 0)) return; + if (value === this) + return this._rejectCallback(makeSelfResolutionError(), false); + var maybePromise = tryConvertToPromise(value, this); + if (!(maybePromise instanceof Promise)) return this._fulfill(value); + + if (shouldBind) this._propagateFrom(maybePromise, 2); + + var promise = maybePromise._target(); + + if (promise === this) { + this._reject(makeSelfResolutionError()); + return; + } + + var bitField = promise._bitField; + if (((bitField & 50397184) === 0)) { + var len = this._length(); + if (len > 0) promise._migrateCallback0(this); + for (var i = 1; i < len; ++i) { + promise._migrateCallbackAt(this, i); + } + this._setFollowing(); + this._setLength(0); + this._setFollowee(promise); + } else if (((bitField & 33554432) !== 0)) { + this._fulfill(promise._value()); + } else if (((bitField & 16777216) !== 0)) { + this._reject(promise._reason()); + } else { + var reason = new CancellationError("late cancellation observer"); + promise._attachExtraTrace(reason); + this._reject(reason); + } +}; + +Promise.prototype._rejectCallback = +function(reason, synchronous, ignoreNonErrorWarnings) { + var trace = util.ensureErrorObject(reason); + var hasStack = trace === reason; + if (!hasStack && !ignoreNonErrorWarnings && debug.warnings()) { + var message = "a promise was rejected with a non-error: " + + util.classString(reason); + this._warn(message, true); + } + this._attachExtraTrace(trace, synchronous ? hasStack : false); + this._reject(reason); +}; + +Promise.prototype._resolveFromExecutor = function (executor) { + if (executor === INTERNAL) return; + var promise = this; + this._captureStackTrace(); + this._pushContext(); + var synchronous = true; + var r = this._execute(executor, function(value) { + promise._resolveCallback(value); + }, function (reason) { + promise._rejectCallback(reason, synchronous); + }); + synchronous = false; + this._popContext(); + + if (r !== undefined) { + promise._rejectCallback(r, true); + } +}; + +Promise.prototype._settlePromiseFromHandler = function ( + handler, receiver, value, promise +) { + var bitField = promise._bitField; + if (((bitField & 65536) !== 0)) return; + promise._pushContext(); + var x; + if (receiver === APPLY) { + if (!value || typeof value.length !== "number") { + x = errorObj; + x.e = new TypeError("cannot .spread() a non-array: " + + util.classString(value)); + } else { + x = tryCatch(handler).apply(this._boundValue(), value); + } + } else { + x = tryCatch(handler).call(receiver, value); + } + var promiseCreated = promise._popContext(); + bitField = promise._bitField; + if (((bitField & 65536) !== 0)) return; + + if (x === NEXT_FILTER) { + promise._reject(value); + } else if (x === errorObj) { + promise._rejectCallback(x.e, false); + } else { + debug.checkForgottenReturns(x, promiseCreated, "", promise, this); + promise._resolveCallback(x); + } +}; + +Promise.prototype._target = function() { + var ret = this; + while (ret._isFollowing()) ret = ret._followee(); + return ret; +}; + +Promise.prototype._followee = function() { + return this._rejectionHandler0; +}; + +Promise.prototype._setFollowee = function(promise) { + this._rejectionHandler0 = promise; +}; + +Promise.prototype._settlePromise = function(promise, handler, receiver, value) { + var isPromise = promise instanceof Promise; + var bitField = this._bitField; + var asyncGuaranteed = ((bitField & 134217728) !== 0); + if (((bitField & 65536) !== 0)) { + if (isPromise) promise._invokeInternalOnCancel(); + + if (receiver instanceof PassThroughHandlerContext && + receiver.isFinallyHandler()) { + receiver.cancelPromise = promise; + if (tryCatch(handler).call(receiver, value) === errorObj) { + promise._reject(errorObj.e); + } + } else if (handler === reflectHandler) { + promise._fulfill(reflectHandler.call(receiver)); + } else if (receiver instanceof Proxyable) { + receiver._promiseCancelled(promise); + } else if (isPromise || promise instanceof PromiseArray) { + promise._cancel(); + } else { + receiver.cancel(); + } + } else if (typeof handler === "function") { + if (!isPromise) { + handler.call(receiver, value, promise); + } else { + if (asyncGuaranteed) promise._setAsyncGuaranteed(); + this._settlePromiseFromHandler(handler, receiver, value, promise); + } + } else if (receiver instanceof Proxyable) { + if (!receiver._isResolved()) { + if (((bitField & 33554432) !== 0)) { + receiver._promiseFulfilled(value, promise); + } else { + receiver._promiseRejected(value, promise); + } + } + } else if (isPromise) { + if (asyncGuaranteed) promise._setAsyncGuaranteed(); + if (((bitField & 33554432) !== 0)) { + promise._fulfill(value); + } else { + promise._reject(value); + } + } +}; + +Promise.prototype._settlePromiseLateCancellationObserver = function(ctx) { + var handler = ctx.handler; + var promise = ctx.promise; + var receiver = ctx.receiver; + var value = ctx.value; + if (typeof handler === "function") { + if (!(promise instanceof Promise)) { + handler.call(receiver, value, promise); + } else { + this._settlePromiseFromHandler(handler, receiver, value, promise); + } + } else if (promise instanceof Promise) { + promise._reject(value); + } +}; + +Promise.prototype._settlePromiseCtx = function(ctx) { + this._settlePromise(ctx.promise, ctx.handler, ctx.receiver, ctx.value); +}; + +Promise.prototype._settlePromise0 = function(handler, value, bitField) { + var promise = this._promise0; + var receiver = this._receiverAt(0); + this._promise0 = undefined; + this._receiver0 = undefined; + this._settlePromise(promise, handler, receiver, value); +}; + +Promise.prototype._clearCallbackDataAtIndex = function(index) { + var base = index * 4 - 4; + this[base + 2] = + this[base + 3] = + this[base + 0] = + this[base + 1] = undefined; +}; + +Promise.prototype._fulfill = function (value) { + var bitField = this._bitField; + if (((bitField & 117506048) >>> 16)) return; + if (value === this) { + var err = makeSelfResolutionError(); + this._attachExtraTrace(err); + return this._reject(err); + } + this._setFulfilled(); + this._rejectionHandler0 = value; + + if ((bitField & 65535) > 0) { + if (((bitField & 134217728) !== 0)) { + this._settlePromises(); + } else { + async.settlePromises(this); + } + this._dereferenceTrace(); + } +}; + +Promise.prototype._reject = function (reason) { + var bitField = this._bitField; + if (((bitField & 117506048) >>> 16)) return; + this._setRejected(); + this._fulfillmentHandler0 = reason; + + if (this._isFinal()) { + return async.fatalError(reason, util.isNode); + } + + if ((bitField & 65535) > 0) { + async.settlePromises(this); + } else { + this._ensurePossibleRejectionHandled(); + } +}; + +Promise.prototype._fulfillPromises = function (len, value) { + for (var i = 1; i < len; i++) { + var handler = this._fulfillmentHandlerAt(i); + var promise = this._promiseAt(i); + var receiver = this._receiverAt(i); + this._clearCallbackDataAtIndex(i); + this._settlePromise(promise, handler, receiver, value); + } +}; + +Promise.prototype._rejectPromises = function (len, reason) { + for (var i = 1; i < len; i++) { + var handler = this._rejectionHandlerAt(i); + var promise = this._promiseAt(i); + var receiver = this._receiverAt(i); + this._clearCallbackDataAtIndex(i); + this._settlePromise(promise, handler, receiver, reason); + } +}; + +Promise.prototype._settlePromises = function () { + var bitField = this._bitField; + var len = (bitField & 65535); + + if (len > 0) { + if (((bitField & 16842752) !== 0)) { + var reason = this._fulfillmentHandler0; + this._settlePromise0(this._rejectionHandler0, reason, bitField); + this._rejectPromises(len, reason); + } else { + var value = this._rejectionHandler0; + this._settlePromise0(this._fulfillmentHandler0, value, bitField); + this._fulfillPromises(len, value); + } + this._setLength(0); + } + this._clearCancellationData(); +}; + +Promise.prototype._settledValue = function() { + var bitField = this._bitField; + if (((bitField & 33554432) !== 0)) { + return this._rejectionHandler0; + } else if (((bitField & 16777216) !== 0)) { + return this._fulfillmentHandler0; + } +}; + +function deferResolve(v) {this.promise._resolveCallback(v);} +function deferReject(v) {this.promise._rejectCallback(v, false);} + +Promise.defer = Promise.pending = function() { + debug.deprecated("Promise.defer", "new Promise"); + var promise = new Promise(INTERNAL); + return { + promise: promise, + resolve: deferResolve, + reject: deferReject + }; +}; + +util.notEnumerableProp(Promise, + "_makeSelfResolutionError", + makeSelfResolutionError); + +_dereq_("./method")(Promise, INTERNAL, tryConvertToPromise, apiRejection, + debug); +_dereq_("./bind")(Promise, INTERNAL, tryConvertToPromise, debug); +_dereq_("./cancel")(Promise, PromiseArray, apiRejection, debug); +_dereq_("./direct_resolve")(Promise); +_dereq_("./synchronous_inspection")(Promise); +_dereq_("./join")( + Promise, PromiseArray, tryConvertToPromise, INTERNAL, async, getDomain); +Promise.Promise = Promise; +Promise.version = "3.5.3"; +_dereq_('./map.js')(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL, debug); +_dereq_('./call_get.js')(Promise); +_dereq_('./using.js')(Promise, apiRejection, tryConvertToPromise, createContext, INTERNAL, debug); +_dereq_('./timers.js')(Promise, INTERNAL, debug); +_dereq_('./generators.js')(Promise, apiRejection, INTERNAL, tryConvertToPromise, Proxyable, debug); +_dereq_('./nodeify.js')(Promise); +_dereq_('./promisify.js')(Promise, INTERNAL); +_dereq_('./props.js')(Promise, PromiseArray, tryConvertToPromise, apiRejection); +_dereq_('./race.js')(Promise, INTERNAL, tryConvertToPromise, apiRejection); +_dereq_('./reduce.js')(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL, debug); +_dereq_('./settle.js')(Promise, PromiseArray, debug); +_dereq_('./some.js')(Promise, PromiseArray, apiRejection); +_dereq_('./filter.js')(Promise, INTERNAL); +_dereq_('./each.js')(Promise, INTERNAL); +_dereq_('./any.js')(Promise); + + util.toFastProperties(Promise); + util.toFastProperties(Promise.prototype); + function fillTypes(value) { + var p = new Promise(INTERNAL); + p._fulfillmentHandler0 = value; + p._rejectionHandler0 = value; + p._promise0 = value; + p._receiver0 = value; + } + // Complete slack tracking, opt out of field-type tracking and + // stabilize map + fillTypes({a: 1}); + fillTypes({b: 2}); + fillTypes({c: 3}); + fillTypes(1); + fillTypes(function(){}); + fillTypes(undefined); + fillTypes(false); + fillTypes(new Promise(INTERNAL)); + debug.setBounds(Async.firstLineError, util.lastLineError); + return Promise; + +}; + +},{"./any.js":1,"./async":2,"./bind":3,"./call_get.js":5,"./cancel":6,"./catch_filter":7,"./context":8,"./debuggability":9,"./direct_resolve":10,"./each.js":11,"./errors":12,"./es5":13,"./filter.js":14,"./finally":15,"./generators.js":16,"./join":17,"./map.js":18,"./method":19,"./nodeback":20,"./nodeify.js":21,"./promise_array":23,"./promisify.js":24,"./props.js":25,"./race.js":27,"./reduce.js":28,"./settle.js":30,"./some.js":31,"./synchronous_inspection":32,"./thenables":33,"./timers.js":34,"./using.js":35,"./util":36}],23:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, INTERNAL, tryConvertToPromise, + apiRejection, Proxyable) { +var util = _dereq_("./util"); +var isArray = util.isArray; + +function toResolutionValue(val) { + switch(val) { + case -2: return []; + case -3: return {}; + case -6: return new Map(); + } +} + +function PromiseArray(values) { + var promise = this._promise = new Promise(INTERNAL); + if (values instanceof Promise) { + promise._propagateFrom(values, 3); + } + promise._setOnCancel(this); + this._values = values; + this._length = 0; + this._totalResolved = 0; + this._init(undefined, -2); +} +util.inherits(PromiseArray, Proxyable); + +PromiseArray.prototype.length = function () { + return this._length; +}; + +PromiseArray.prototype.promise = function () { + return this._promise; +}; + +PromiseArray.prototype._init = function init(_, resolveValueIfEmpty) { + var values = tryConvertToPromise(this._values, this._promise); + if (values instanceof Promise) { + values = values._target(); + var bitField = values._bitField; + ; + this._values = values; + + if (((bitField & 50397184) === 0)) { + this._promise._setAsyncGuaranteed(); + return values._then( + init, + this._reject, + undefined, + this, + resolveValueIfEmpty + ); + } else if (((bitField & 33554432) !== 0)) { + values = values._value(); + } else if (((bitField & 16777216) !== 0)) { + return this._reject(values._reason()); + } else { + return this._cancel(); + } + } + values = util.asArray(values); + if (values === null) { + var err = apiRejection( + "expecting an array or an iterable object but got " + util.classString(values)).reason(); + this._promise._rejectCallback(err, false); + return; + } + + if (values.length === 0) { + if (resolveValueIfEmpty === -5) { + this._resolveEmptyArray(); + } + else { + this._resolve(toResolutionValue(resolveValueIfEmpty)); + } + return; + } + this._iterate(values); +}; + +PromiseArray.prototype._iterate = function(values) { + var len = this.getActualLength(values.length); + this._length = len; + this._values = this.shouldCopyValues() ? new Array(len) : this._values; + var result = this._promise; + var isResolved = false; + var bitField = null; + for (var i = 0; i < len; ++i) { + var maybePromise = tryConvertToPromise(values[i], result); + + if (maybePromise instanceof Promise) { + maybePromise = maybePromise._target(); + bitField = maybePromise._bitField; + } else { + bitField = null; + } + + if (isResolved) { + if (bitField !== null) { + maybePromise.suppressUnhandledRejections(); + } + } else if (bitField !== null) { + if (((bitField & 50397184) === 0)) { + maybePromise._proxy(this, i); + this._values[i] = maybePromise; + } else if (((bitField & 33554432) !== 0)) { + isResolved = this._promiseFulfilled(maybePromise._value(), i); + } else if (((bitField & 16777216) !== 0)) { + isResolved = this._promiseRejected(maybePromise._reason(), i); + } else { + isResolved = this._promiseCancelled(i); + } + } else { + isResolved = this._promiseFulfilled(maybePromise, i); + } + } + if (!isResolved) result._setAsyncGuaranteed(); +}; + +PromiseArray.prototype._isResolved = function () { + return this._values === null; +}; + +PromiseArray.prototype._resolve = function (value) { + this._values = null; + this._promise._fulfill(value); +}; + +PromiseArray.prototype._cancel = function() { + if (this._isResolved() || !this._promise._isCancellable()) return; + this._values = null; + this._promise._cancel(); +}; + +PromiseArray.prototype._reject = function (reason) { + this._values = null; + this._promise._rejectCallback(reason, false); +}; + +PromiseArray.prototype._promiseFulfilled = function (value, index) { + this._values[index] = value; + var totalResolved = ++this._totalResolved; + if (totalResolved >= this._length) { + this._resolve(this._values); + return true; + } + return false; +}; + +PromiseArray.prototype._promiseCancelled = function() { + this._cancel(); + return true; +}; + +PromiseArray.prototype._promiseRejected = function (reason) { + this._totalResolved++; + this._reject(reason); + return true; +}; + +PromiseArray.prototype._resultCancelled = function() { + if (this._isResolved()) return; + var values = this._values; + this._cancel(); + if (values instanceof Promise) { + values.cancel(); + } else { + for (var i = 0; i < values.length; ++i) { + if (values[i] instanceof Promise) { + values[i].cancel(); + } + } + } +}; + +PromiseArray.prototype.shouldCopyValues = function () { + return true; +}; + +PromiseArray.prototype.getActualLength = function (len) { + return len; +}; + +return PromiseArray; +}; + +},{"./util":36}],24:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, INTERNAL) { +var THIS = {}; +var util = _dereq_("./util"); +var nodebackForPromise = _dereq_("./nodeback"); +var withAppended = util.withAppended; +var maybeWrapAsError = util.maybeWrapAsError; +var canEvaluate = util.canEvaluate; +var TypeError = _dereq_("./errors").TypeError; +var defaultSuffix = "Async"; +var defaultPromisified = {__isPromisified__: true}; +var noCopyProps = [ + "arity", "length", + "name", + "arguments", + "caller", + "callee", + "prototype", + "__isPromisified__" +]; +var noCopyPropsPattern = new RegExp("^(?:" + noCopyProps.join("|") + ")$"); + +var defaultFilter = function(name) { + return util.isIdentifier(name) && + name.charAt(0) !== "_" && + name !== "constructor"; +}; + +function propsFilter(key) { + return !noCopyPropsPattern.test(key); +} + +function isPromisified(fn) { + try { + return fn.__isPromisified__ === true; + } + catch (e) { + return false; + } +} + +function hasPromisified(obj, key, suffix) { + var val = util.getDataPropertyOrDefault(obj, key + suffix, + defaultPromisified); + return val ? isPromisified(val) : false; +} +function checkValid(ret, suffix, suffixRegexp) { + for (var i = 0; i < ret.length; i += 2) { + var key = ret[i]; + if (suffixRegexp.test(key)) { + var keyWithoutAsyncSuffix = key.replace(suffixRegexp, ""); + for (var j = 0; j < ret.length; j += 2) { + if (ret[j] === keyWithoutAsyncSuffix) { + throw new TypeError("Cannot promisify an API that has normal methods with '%s'-suffix\u000a\u000a See http://goo.gl/MqrFmX\u000a" + .replace("%s", suffix)); + } + } + } + } +} + +function promisifiableMethods(obj, suffix, suffixRegexp, filter) { + var keys = util.inheritedDataKeys(obj); + var ret = []; + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + var value = obj[key]; + var passesDefaultFilter = filter === defaultFilter + ? true : defaultFilter(key, value, obj); + if (typeof value === "function" && + !isPromisified(value) && + !hasPromisified(obj, key, suffix) && + filter(key, value, obj, passesDefaultFilter)) { + ret.push(key, value); + } + } + checkValid(ret, suffix, suffixRegexp); + return ret; +} + +var escapeIdentRegex = function(str) { + return str.replace(/([$])/, "\\$"); +}; + +var makeNodePromisifiedEval; +if (!true) { +var switchCaseArgumentOrder = function(likelyArgumentCount) { + var ret = [likelyArgumentCount]; + var min = Math.max(0, likelyArgumentCount - 1 - 3); + for(var i = likelyArgumentCount - 1; i >= min; --i) { + ret.push(i); + } + for(var i = likelyArgumentCount + 1; i <= 3; ++i) { + ret.push(i); + } + return ret; +}; + +var argumentSequence = function(argumentCount) { + return util.filledRange(argumentCount, "_arg", ""); +}; + +var parameterDeclaration = function(parameterCount) { + return util.filledRange( + Math.max(parameterCount, 3), "_arg", ""); +}; + +var parameterCount = function(fn) { + if (typeof fn.length === "number") { + return Math.max(Math.min(fn.length, 1023 + 1), 0); + } + return 0; +}; + +makeNodePromisifiedEval = +function(callback, receiver, originalName, fn, _, multiArgs) { + var newParameterCount = Math.max(0, parameterCount(fn) - 1); + var argumentOrder = switchCaseArgumentOrder(newParameterCount); + var shouldProxyThis = typeof callback === "string" || receiver === THIS; + + function generateCallForArgumentCount(count) { + var args = argumentSequence(count).join(", "); + var comma = count > 0 ? ", " : ""; + var ret; + if (shouldProxyThis) { + ret = "ret = callback.call(this, {{args}}, nodeback); break;\n"; + } else { + ret = receiver === undefined + ? "ret = callback({{args}}, nodeback); break;\n" + : "ret = callback.call(receiver, {{args}}, nodeback); break;\n"; + } + return ret.replace("{{args}}", args).replace(", ", comma); + } + + function generateArgumentSwitchCase() { + var ret = ""; + for (var i = 0; i < argumentOrder.length; ++i) { + ret += "case " + argumentOrder[i] +":" + + generateCallForArgumentCount(argumentOrder[i]); + } + + ret += " \n\ + default: \n\ + var args = new Array(len + 1); \n\ + var i = 0; \n\ + for (var i = 0; i < len; ++i) { \n\ + args[i] = arguments[i]; \n\ + } \n\ + args[i] = nodeback; \n\ + [CodeForCall] \n\ + break; \n\ + ".replace("[CodeForCall]", (shouldProxyThis + ? "ret = callback.apply(this, args);\n" + : "ret = callback.apply(receiver, args);\n")); + return ret; + } + + var getFunctionCode = typeof callback === "string" + ? ("this != null ? this['"+callback+"'] : fn") + : "fn"; + var body = "'use strict'; \n\ + var ret = function (Parameters) { \n\ + 'use strict'; \n\ + var len = arguments.length; \n\ + var promise = new Promise(INTERNAL); \n\ + promise._captureStackTrace(); \n\ + var nodeback = nodebackForPromise(promise, " + multiArgs + "); \n\ + var ret; \n\ + var callback = tryCatch([GetFunctionCode]); \n\ + switch(len) { \n\ + [CodeForSwitchCase] \n\ + } \n\ + if (ret === errorObj) { \n\ + promise._rejectCallback(maybeWrapAsError(ret.e), true, true);\n\ + } \n\ + if (!promise._isFateSealed()) promise._setAsyncGuaranteed(); \n\ + return promise; \n\ + }; \n\ + notEnumerableProp(ret, '__isPromisified__', true); \n\ + return ret; \n\ + ".replace("[CodeForSwitchCase]", generateArgumentSwitchCase()) + .replace("[GetFunctionCode]", getFunctionCode); + body = body.replace("Parameters", parameterDeclaration(newParameterCount)); + return new Function("Promise", + "fn", + "receiver", + "withAppended", + "maybeWrapAsError", + "nodebackForPromise", + "tryCatch", + "errorObj", + "notEnumerableProp", + "INTERNAL", + body)( + Promise, + fn, + receiver, + withAppended, + maybeWrapAsError, + nodebackForPromise, + util.tryCatch, + util.errorObj, + util.notEnumerableProp, + INTERNAL); +}; +} + +function makeNodePromisifiedClosure(callback, receiver, _, fn, __, multiArgs) { + var defaultThis = (function() {return this;})(); + var method = callback; + if (typeof method === "string") { + callback = fn; + } + function promisified() { + var _receiver = receiver; + if (receiver === THIS) _receiver = this; + var promise = new Promise(INTERNAL); + promise._captureStackTrace(); + var cb = typeof method === "string" && this !== defaultThis + ? this[method] : callback; + var fn = nodebackForPromise(promise, multiArgs); + try { + cb.apply(_receiver, withAppended(arguments, fn)); + } catch(e) { + promise._rejectCallback(maybeWrapAsError(e), true, true); + } + if (!promise._isFateSealed()) promise._setAsyncGuaranteed(); + return promise; + } + util.notEnumerableProp(promisified, "__isPromisified__", true); + return promisified; +} + +var makeNodePromisified = canEvaluate + ? makeNodePromisifiedEval + : makeNodePromisifiedClosure; + +function promisifyAll(obj, suffix, filter, promisifier, multiArgs) { + var suffixRegexp = new RegExp(escapeIdentRegex(suffix) + "$"); + var methods = + promisifiableMethods(obj, suffix, suffixRegexp, filter); + + for (var i = 0, len = methods.length; i < len; i+= 2) { + var key = methods[i]; + var fn = methods[i+1]; + var promisifiedKey = key + suffix; + if (promisifier === makeNodePromisified) { + obj[promisifiedKey] = + makeNodePromisified(key, THIS, key, fn, suffix, multiArgs); + } else { + var promisified = promisifier(fn, function() { + return makeNodePromisified(key, THIS, key, + fn, suffix, multiArgs); + }); + util.notEnumerableProp(promisified, "__isPromisified__", true); + obj[promisifiedKey] = promisified; + } + } + util.toFastProperties(obj); + return obj; +} + +function promisify(callback, receiver, multiArgs) { + return makeNodePromisified(callback, receiver, undefined, + callback, null, multiArgs); +} + +Promise.promisify = function (fn, options) { + if (typeof fn !== "function") { + throw new TypeError("expecting a function but got " + util.classString(fn)); + } + if (isPromisified(fn)) { + return fn; + } + options = Object(options); + var receiver = options.context === undefined ? THIS : options.context; + var multiArgs = !!options.multiArgs; + var ret = promisify(fn, receiver, multiArgs); + util.copyDescriptors(fn, ret, propsFilter); + return ret; +}; + +Promise.promisifyAll = function (target, options) { + if (typeof target !== "function" && typeof target !== "object") { + throw new TypeError("the target of promisifyAll must be an object or a function\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + options = Object(options); + var multiArgs = !!options.multiArgs; + var suffix = options.suffix; + if (typeof suffix !== "string") suffix = defaultSuffix; + var filter = options.filter; + if (typeof filter !== "function") filter = defaultFilter; + var promisifier = options.promisifier; + if (typeof promisifier !== "function") promisifier = makeNodePromisified; + + if (!util.isIdentifier(suffix)) { + throw new RangeError("suffix must be a valid identifier\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + + var keys = util.inheritedDataKeys(target); + for (var i = 0; i < keys.length; ++i) { + var value = target[keys[i]]; + if (keys[i] !== "constructor" && + util.isClass(value)) { + promisifyAll(value.prototype, suffix, filter, promisifier, + multiArgs); + promisifyAll(value, suffix, filter, promisifier, multiArgs); + } + } + + return promisifyAll(target, suffix, filter, promisifier, multiArgs); +}; +}; + + +},{"./errors":12,"./nodeback":20,"./util":36}],25:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function( + Promise, PromiseArray, tryConvertToPromise, apiRejection) { +var util = _dereq_("./util"); +var isObject = util.isObject; +var es5 = _dereq_("./es5"); +var Es6Map; +if (typeof Map === "function") Es6Map = Map; + +var mapToEntries = (function() { + var index = 0; + var size = 0; + + function extractEntry(value, key) { + this[index] = value; + this[index + size] = key; + index++; + } + + return function mapToEntries(map) { + size = map.size; + index = 0; + var ret = new Array(map.size * 2); + map.forEach(extractEntry, ret); + return ret; + }; +})(); + +var entriesToMap = function(entries) { + var ret = new Es6Map(); + var length = entries.length / 2 | 0; + for (var i = 0; i < length; ++i) { + var key = entries[length + i]; + var value = entries[i]; + ret.set(key, value); + } + return ret; +}; + +function PropertiesPromiseArray(obj) { + var isMap = false; + var entries; + if (Es6Map !== undefined && obj instanceof Es6Map) { + entries = mapToEntries(obj); + isMap = true; + } else { + var keys = es5.keys(obj); + var len = keys.length; + entries = new Array(len * 2); + for (var i = 0; i < len; ++i) { + var key = keys[i]; + entries[i] = obj[key]; + entries[i + len] = key; + } + } + this.constructor$(entries); + this._isMap = isMap; + this._init$(undefined, isMap ? -6 : -3); +} +util.inherits(PropertiesPromiseArray, PromiseArray); + +PropertiesPromiseArray.prototype._init = function () {}; + +PropertiesPromiseArray.prototype._promiseFulfilled = function (value, index) { + this._values[index] = value; + var totalResolved = ++this._totalResolved; + if (totalResolved >= this._length) { + var val; + if (this._isMap) { + val = entriesToMap(this._values); + } else { + val = {}; + var keyOffset = this.length(); + for (var i = 0, len = this.length(); i < len; ++i) { + val[this._values[i + keyOffset]] = this._values[i]; + } + } + this._resolve(val); + return true; + } + return false; +}; + +PropertiesPromiseArray.prototype.shouldCopyValues = function () { + return false; +}; + +PropertiesPromiseArray.prototype.getActualLength = function (len) { + return len >> 1; +}; + +function props(promises) { + var ret; + var castValue = tryConvertToPromise(promises); + + if (!isObject(castValue)) { + return apiRejection("cannot await properties of a non-object\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } else if (castValue instanceof Promise) { + ret = castValue._then( + Promise.props, undefined, undefined, undefined, undefined); + } else { + ret = new PropertiesPromiseArray(castValue).promise(); + } + + if (castValue instanceof Promise) { + ret._propagateFrom(castValue, 2); + } + return ret; +} + +Promise.prototype.props = function () { + return props(this); +}; + +Promise.props = function (promises) { + return props(promises); +}; +}; + +},{"./es5":13,"./util":36}],26:[function(_dereq_,module,exports){ +"use strict"; +function arrayMove(src, srcIndex, dst, dstIndex, len) { + for (var j = 0; j < len; ++j) { + dst[j + dstIndex] = src[j + srcIndex]; + src[j + srcIndex] = void 0; + } +} + +function Queue(capacity) { + this._capacity = capacity; + this._length = 0; + this._front = 0; +} + +Queue.prototype._willBeOverCapacity = function (size) { + return this._capacity < size; +}; + +Queue.prototype._pushOne = function (arg) { + var length = this.length(); + this._checkCapacity(length + 1); + var i = (this._front + length) & (this._capacity - 1); + this[i] = arg; + this._length = length + 1; +}; + +Queue.prototype.push = function (fn, receiver, arg) { + var length = this.length() + 3; + if (this._willBeOverCapacity(length)) { + this._pushOne(fn); + this._pushOne(receiver); + this._pushOne(arg); + return; + } + var j = this._front + length - 3; + this._checkCapacity(length); + var wrapMask = this._capacity - 1; + this[(j + 0) & wrapMask] = fn; + this[(j + 1) & wrapMask] = receiver; + this[(j + 2) & wrapMask] = arg; + this._length = length; +}; + +Queue.prototype.shift = function () { + var front = this._front, + ret = this[front]; + + this[front] = undefined; + this._front = (front + 1) & (this._capacity - 1); + this._length--; + return ret; +}; + +Queue.prototype.length = function () { + return this._length; +}; + +Queue.prototype._checkCapacity = function (size) { + if (this._capacity < size) { + this._resizeTo(this._capacity << 1); + } +}; + +Queue.prototype._resizeTo = function (capacity) { + var oldCapacity = this._capacity; + this._capacity = capacity; + var front = this._front; + var length = this._length; + var moveItemsCount = (front + length) & (oldCapacity - 1); + arrayMove(this, 0, this, oldCapacity, moveItemsCount); +}; + +module.exports = Queue; + +},{}],27:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function( + Promise, INTERNAL, tryConvertToPromise, apiRejection) { +var util = _dereq_("./util"); + +var raceLater = function (promise) { + return promise.then(function(array) { + return race(array, promise); + }); +}; + +function race(promises, parent) { + var maybePromise = tryConvertToPromise(promises); + + if (maybePromise instanceof Promise) { + return raceLater(maybePromise); + } else { + promises = util.asArray(promises); + if (promises === null) + return apiRejection("expecting an array or an iterable object but got " + util.classString(promises)); + } + + var ret = new Promise(INTERNAL); + if (parent !== undefined) { + ret._propagateFrom(parent, 3); + } + var fulfill = ret._fulfill; + var reject = ret._reject; + for (var i = 0, len = promises.length; i < len; ++i) { + var val = promises[i]; + + if (val === undefined && !(i in promises)) { + continue; + } + + Promise.cast(val)._then(fulfill, reject, undefined, ret, null); + } + return ret; +} + +Promise.race = function (promises) { + return race(promises, undefined); +}; + +Promise.prototype.race = function () { + return race(this, undefined); +}; + +}; + +},{"./util":36}],28:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, + PromiseArray, + apiRejection, + tryConvertToPromise, + INTERNAL, + debug) { +var getDomain = Promise._getDomain; +var util = _dereq_("./util"); +var tryCatch = util.tryCatch; + +function ReductionPromiseArray(promises, fn, initialValue, _each) { + this.constructor$(promises); + var domain = getDomain(); + this._fn = domain === null ? fn : util.domainBind(domain, fn); + if (initialValue !== undefined) { + initialValue = Promise.resolve(initialValue); + initialValue._attachCancellationCallback(this); + } + this._initialValue = initialValue; + this._currentCancellable = null; + if(_each === INTERNAL) { + this._eachValues = Array(this._length); + } else if (_each === 0) { + this._eachValues = null; + } else { + this._eachValues = undefined; + } + this._promise._captureStackTrace(); + this._init$(undefined, -5); +} +util.inherits(ReductionPromiseArray, PromiseArray); + +ReductionPromiseArray.prototype._gotAccum = function(accum) { + if (this._eachValues !== undefined && + this._eachValues !== null && + accum !== INTERNAL) { + this._eachValues.push(accum); + } +}; + +ReductionPromiseArray.prototype._eachComplete = function(value) { + if (this._eachValues !== null) { + this._eachValues.push(value); + } + return this._eachValues; +}; + +ReductionPromiseArray.prototype._init = function() {}; + +ReductionPromiseArray.prototype._resolveEmptyArray = function() { + this._resolve(this._eachValues !== undefined ? this._eachValues + : this._initialValue); +}; + +ReductionPromiseArray.prototype.shouldCopyValues = function () { + return false; +}; + +ReductionPromiseArray.prototype._resolve = function(value) { + this._promise._resolveCallback(value); + this._values = null; +}; + +ReductionPromiseArray.prototype._resultCancelled = function(sender) { + if (sender === this._initialValue) return this._cancel(); + if (this._isResolved()) return; + this._resultCancelled$(); + if (this._currentCancellable instanceof Promise) { + this._currentCancellable.cancel(); + } + if (this._initialValue instanceof Promise) { + this._initialValue.cancel(); + } +}; + +ReductionPromiseArray.prototype._iterate = function (values) { + this._values = values; + var value; + var i; + var length = values.length; + if (this._initialValue !== undefined) { + value = this._initialValue; + i = 0; + } else { + value = Promise.resolve(values[0]); + i = 1; + } + + this._currentCancellable = value; + + if (!value.isRejected()) { + for (; i < length; ++i) { + var ctx = { + accum: null, + value: values[i], + index: i, + length: length, + array: this + }; + value = value._then(gotAccum, undefined, undefined, ctx, undefined); + } + } + + if (this._eachValues !== undefined) { + value = value + ._then(this._eachComplete, undefined, undefined, this, undefined); + } + value._then(completed, completed, undefined, value, this); +}; + +Promise.prototype.reduce = function (fn, initialValue) { + return reduce(this, fn, initialValue, null); +}; + +Promise.reduce = function (promises, fn, initialValue, _each) { + return reduce(promises, fn, initialValue, _each); +}; + +function completed(valueOrReason, array) { + if (this.isFulfilled()) { + array._resolve(valueOrReason); + } else { + array._reject(valueOrReason); + } +} + +function reduce(promises, fn, initialValue, _each) { + if (typeof fn !== "function") { + return apiRejection("expecting a function but got " + util.classString(fn)); + } + var array = new ReductionPromiseArray(promises, fn, initialValue, _each); + return array.promise(); +} + +function gotAccum(accum) { + this.accum = accum; + this.array._gotAccum(accum); + var value = tryConvertToPromise(this.value, this.array._promise); + if (value instanceof Promise) { + this.array._currentCancellable = value; + return value._then(gotValue, undefined, undefined, this, undefined); + } else { + return gotValue.call(this, value); + } +} + +function gotValue(value) { + var array = this.array; + var promise = array._promise; + var fn = tryCatch(array._fn); + promise._pushContext(); + var ret; + if (array._eachValues !== undefined) { + ret = fn.call(promise._boundValue(), value, this.index, this.length); + } else { + ret = fn.call(promise._boundValue(), + this.accum, value, this.index, this.length); + } + if (ret instanceof Promise) { + array._currentCancellable = ret; + } + var promiseCreated = promise._popContext(); + debug.checkForgottenReturns( + ret, + promiseCreated, + array._eachValues !== undefined ? "Promise.each" : "Promise.reduce", + promise + ); + return ret; +} +}; + +},{"./util":36}],29:[function(_dereq_,module,exports){ +"use strict"; +var util = _dereq_("./util"); +var schedule; +var noAsyncScheduler = function() { + throw new Error("No async scheduler available\u000a\u000a See http://goo.gl/MqrFmX\u000a"); +}; +var NativePromise = util.getNativePromise(); +if (util.isNode && typeof MutationObserver === "undefined") { + var GlobalSetImmediate = global.setImmediate; + var ProcessNextTick = process.nextTick; + schedule = util.isRecentNode + ? function(fn) { GlobalSetImmediate.call(global, fn); } + : function(fn) { ProcessNextTick.call(process, fn); }; +} else if (typeof NativePromise === "function" && + typeof NativePromise.resolve === "function") { + var nativePromise = NativePromise.resolve(); + schedule = function(fn) { + nativePromise.then(fn); + }; +} else if ((typeof MutationObserver !== "undefined") && + !(typeof window !== "undefined" && + window.navigator && + (window.navigator.standalone || window.cordova))) { + schedule = (function() { + var div = document.createElement("div"); + var opts = {attributes: true}; + var toggleScheduled = false; + var div2 = document.createElement("div"); + var o2 = new MutationObserver(function() { + div.classList.toggle("foo"); + toggleScheduled = false; + }); + o2.observe(div2, opts); + + var scheduleToggle = function() { + if (toggleScheduled) return; + toggleScheduled = true; + div2.classList.toggle("foo"); + }; + + return function schedule(fn) { + var o = new MutationObserver(function() { + o.disconnect(); + fn(); + }); + o.observe(div, opts); + scheduleToggle(); + }; + })(); +} else if (typeof setImmediate !== "undefined") { + schedule = function (fn) { + setImmediate(fn); + }; +} else if (typeof setTimeout !== "undefined") { + schedule = function (fn) { + setTimeout(fn, 0); + }; +} else { + schedule = noAsyncScheduler; +} +module.exports = schedule; + +},{"./util":36}],30:[function(_dereq_,module,exports){ +"use strict"; +module.exports = + function(Promise, PromiseArray, debug) { +var PromiseInspection = Promise.PromiseInspection; +var util = _dereq_("./util"); + +function SettledPromiseArray(values) { + this.constructor$(values); +} +util.inherits(SettledPromiseArray, PromiseArray); + +SettledPromiseArray.prototype._promiseResolved = function (index, inspection) { + this._values[index] = inspection; + var totalResolved = ++this._totalResolved; + if (totalResolved >= this._length) { + this._resolve(this._values); + return true; + } + return false; +}; + +SettledPromiseArray.prototype._promiseFulfilled = function (value, index) { + var ret = new PromiseInspection(); + ret._bitField = 33554432; + ret._settledValueField = value; + return this._promiseResolved(index, ret); +}; +SettledPromiseArray.prototype._promiseRejected = function (reason, index) { + var ret = new PromiseInspection(); + ret._bitField = 16777216; + ret._settledValueField = reason; + return this._promiseResolved(index, ret); +}; + +Promise.settle = function (promises) { + debug.deprecated(".settle()", ".reflect()"); + return new SettledPromiseArray(promises).promise(); +}; + +Promise.prototype.settle = function () { + return Promise.settle(this); +}; +}; + +},{"./util":36}],31:[function(_dereq_,module,exports){ +"use strict"; +module.exports = +function(Promise, PromiseArray, apiRejection) { +var util = _dereq_("./util"); +var RangeError = _dereq_("./errors").RangeError; +var AggregateError = _dereq_("./errors").AggregateError; +var isArray = util.isArray; +var CANCELLATION = {}; + + +function SomePromiseArray(values) { + this.constructor$(values); + this._howMany = 0; + this._unwrap = false; + this._initialized = false; +} +util.inherits(SomePromiseArray, PromiseArray); + +SomePromiseArray.prototype._init = function () { + if (!this._initialized) { + return; + } + if (this._howMany === 0) { + this._resolve([]); + return; + } + this._init$(undefined, -5); + var isArrayResolved = isArray(this._values); + if (!this._isResolved() && + isArrayResolved && + this._howMany > this._canPossiblyFulfill()) { + this._reject(this._getRangeError(this.length())); + } +}; + +SomePromiseArray.prototype.init = function () { + this._initialized = true; + this._init(); +}; + +SomePromiseArray.prototype.setUnwrap = function () { + this._unwrap = true; +}; + +SomePromiseArray.prototype.howMany = function () { + return this._howMany; +}; + +SomePromiseArray.prototype.setHowMany = function (count) { + this._howMany = count; +}; + +SomePromiseArray.prototype._promiseFulfilled = function (value) { + this._addFulfilled(value); + if (this._fulfilled() === this.howMany()) { + this._values.length = this.howMany(); + if (this.howMany() === 1 && this._unwrap) { + this._resolve(this._values[0]); + } else { + this._resolve(this._values); + } + return true; + } + return false; + +}; +SomePromiseArray.prototype._promiseRejected = function (reason) { + this._addRejected(reason); + return this._checkOutcome(); +}; + +SomePromiseArray.prototype._promiseCancelled = function () { + if (this._values instanceof Promise || this._values == null) { + return this._cancel(); + } + this._addRejected(CANCELLATION); + return this._checkOutcome(); +}; + +SomePromiseArray.prototype._checkOutcome = function() { + if (this.howMany() > this._canPossiblyFulfill()) { + var e = new AggregateError(); + for (var i = this.length(); i < this._values.length; ++i) { + if (this._values[i] !== CANCELLATION) { + e.push(this._values[i]); + } + } + if (e.length > 0) { + this._reject(e); + } else { + this._cancel(); + } + return true; + } + return false; +}; + +SomePromiseArray.prototype._fulfilled = function () { + return this._totalResolved; +}; + +SomePromiseArray.prototype._rejected = function () { + return this._values.length - this.length(); +}; + +SomePromiseArray.prototype._addRejected = function (reason) { + this._values.push(reason); +}; + +SomePromiseArray.prototype._addFulfilled = function (value) { + this._values[this._totalResolved++] = value; +}; + +SomePromiseArray.prototype._canPossiblyFulfill = function () { + return this.length() - this._rejected(); +}; + +SomePromiseArray.prototype._getRangeError = function (count) { + var message = "Input array must contain at least " + + this._howMany + " items but contains only " + count + " items"; + return new RangeError(message); +}; + +SomePromiseArray.prototype._resolveEmptyArray = function () { + this._reject(this._getRangeError(0)); +}; + +function some(promises, howMany) { + if ((howMany | 0) !== howMany || howMany < 0) { + return apiRejection("expecting a positive integer\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + var ret = new SomePromiseArray(promises); + var promise = ret.promise(); + ret.setHowMany(howMany); + ret.init(); + return promise; +} + +Promise.some = function (promises, howMany) { + return some(promises, howMany); +}; + +Promise.prototype.some = function (howMany) { + return some(this, howMany); +}; + +Promise._SomePromiseArray = SomePromiseArray; +}; + +},{"./errors":12,"./util":36}],32:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise) { +function PromiseInspection(promise) { + if (promise !== undefined) { + promise = promise._target(); + this._bitField = promise._bitField; + this._settledValueField = promise._isFateSealed() + ? promise._settledValue() : undefined; + } + else { + this._bitField = 0; + this._settledValueField = undefined; + } +} + +PromiseInspection.prototype._settledValue = function() { + return this._settledValueField; +}; + +var value = PromiseInspection.prototype.value = function () { + if (!this.isFulfilled()) { + throw new TypeError("cannot get fulfillment value of a non-fulfilled promise\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + return this._settledValue(); +}; + +var reason = PromiseInspection.prototype.error = +PromiseInspection.prototype.reason = function () { + if (!this.isRejected()) { + throw new TypeError("cannot get rejection reason of a non-rejected promise\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + return this._settledValue(); +}; + +var isFulfilled = PromiseInspection.prototype.isFulfilled = function() { + return (this._bitField & 33554432) !== 0; +}; + +var isRejected = PromiseInspection.prototype.isRejected = function () { + return (this._bitField & 16777216) !== 0; +}; + +var isPending = PromiseInspection.prototype.isPending = function () { + return (this._bitField & 50397184) === 0; +}; + +var isResolved = PromiseInspection.prototype.isResolved = function () { + return (this._bitField & 50331648) !== 0; +}; + +PromiseInspection.prototype.isCancelled = function() { + return (this._bitField & 8454144) !== 0; +}; + +Promise.prototype.__isCancelled = function() { + return (this._bitField & 65536) === 65536; +}; + +Promise.prototype._isCancelled = function() { + return this._target().__isCancelled(); +}; + +Promise.prototype.isCancelled = function() { + return (this._target()._bitField & 8454144) !== 0; +}; + +Promise.prototype.isPending = function() { + return isPending.call(this._target()); +}; + +Promise.prototype.isRejected = function() { + return isRejected.call(this._target()); +}; + +Promise.prototype.isFulfilled = function() { + return isFulfilled.call(this._target()); +}; + +Promise.prototype.isResolved = function() { + return isResolved.call(this._target()); +}; + +Promise.prototype.value = function() { + return value.call(this._target()); +}; + +Promise.prototype.reason = function() { + var target = this._target(); + target._unsetRejectionIsUnhandled(); + return reason.call(target); +}; + +Promise.prototype._value = function() { + return this._settledValue(); +}; + +Promise.prototype._reason = function() { + this._unsetRejectionIsUnhandled(); + return this._settledValue(); +}; + +Promise.PromiseInspection = PromiseInspection; +}; + +},{}],33:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, INTERNAL) { +var util = _dereq_("./util"); +var errorObj = util.errorObj; +var isObject = util.isObject; + +function tryConvertToPromise(obj, context) { + if (isObject(obj)) { + if (obj instanceof Promise) return obj; + var then = getThen(obj); + if (then === errorObj) { + if (context) context._pushContext(); + var ret = Promise.reject(then.e); + if (context) context._popContext(); + return ret; + } else if (typeof then === "function") { + if (isAnyBluebirdPromise(obj)) { + var ret = new Promise(INTERNAL); + obj._then( + ret._fulfill, + ret._reject, + undefined, + ret, + null + ); + return ret; + } + return doThenable(obj, then, context); + } + } + return obj; +} + +function doGetThen(obj) { + return obj.then; +} + +function getThen(obj) { + try { + return doGetThen(obj); + } catch (e) { + errorObj.e = e; + return errorObj; + } +} + +var hasProp = {}.hasOwnProperty; +function isAnyBluebirdPromise(obj) { + try { + return hasProp.call(obj, "_promise0"); + } catch (e) { + return false; + } +} + +function doThenable(x, then, context) { + var promise = new Promise(INTERNAL); + var ret = promise; + if (context) context._pushContext(); + promise._captureStackTrace(); + if (context) context._popContext(); + var synchronous = true; + var result = util.tryCatch(then).call(x, resolve, reject); + synchronous = false; + + if (promise && result === errorObj) { + promise._rejectCallback(result.e, true, true); + promise = null; + } + + function resolve(value) { + if (!promise) return; + promise._resolveCallback(value); + promise = null; + } + + function reject(reason) { + if (!promise) return; + promise._rejectCallback(reason, synchronous, true); + promise = null; + } + return ret; +} + +return tryConvertToPromise; +}; + +},{"./util":36}],34:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function(Promise, INTERNAL, debug) { +var util = _dereq_("./util"); +var TimeoutError = Promise.TimeoutError; + +function HandleWrapper(handle) { + this.handle = handle; +} + +HandleWrapper.prototype._resultCancelled = function() { + clearTimeout(this.handle); +}; + +var afterValue = function(value) { return delay(+this).thenReturn(value); }; +var delay = Promise.delay = function (ms, value) { + var ret; + var handle; + if (value !== undefined) { + ret = Promise.resolve(value) + ._then(afterValue, null, null, ms, undefined); + if (debug.cancellation() && value instanceof Promise) { + ret._setOnCancel(value); + } + } else { + ret = new Promise(INTERNAL); + handle = setTimeout(function() { ret._fulfill(); }, +ms); + if (debug.cancellation()) { + ret._setOnCancel(new HandleWrapper(handle)); + } + ret._captureStackTrace(); + } + ret._setAsyncGuaranteed(); + return ret; +}; + +Promise.prototype.delay = function (ms) { + return delay(ms, this); +}; + +var afterTimeout = function (promise, message, parent) { + var err; + if (typeof message !== "string") { + if (message instanceof Error) { + err = message; + } else { + err = new TimeoutError("operation timed out"); + } + } else { + err = new TimeoutError(message); + } + util.markAsOriginatingFromRejection(err); + promise._attachExtraTrace(err); + promise._reject(err); + + if (parent != null) { + parent.cancel(); + } +}; + +function successClear(value) { + clearTimeout(this.handle); + return value; +} + +function failureClear(reason) { + clearTimeout(this.handle); + throw reason; +} + +Promise.prototype.timeout = function (ms, message) { + ms = +ms; + var ret, parent; + + var handleWrapper = new HandleWrapper(setTimeout(function timeoutTimeout() { + if (ret.isPending()) { + afterTimeout(ret, message, parent); + } + }, ms)); + + if (debug.cancellation()) { + parent = this.then(); + ret = parent._then(successClear, failureClear, + undefined, handleWrapper, undefined); + ret._setOnCancel(handleWrapper); + } else { + ret = this._then(successClear, failureClear, + undefined, handleWrapper, undefined); + } + + return ret; +}; + +}; + +},{"./util":36}],35:[function(_dereq_,module,exports){ +"use strict"; +module.exports = function (Promise, apiRejection, tryConvertToPromise, + createContext, INTERNAL, debug) { + var util = _dereq_("./util"); + var TypeError = _dereq_("./errors").TypeError; + var inherits = _dereq_("./util").inherits; + var errorObj = util.errorObj; + var tryCatch = util.tryCatch; + var NULL = {}; + + function thrower(e) { + setTimeout(function(){throw e;}, 0); + } + + function castPreservingDisposable(thenable) { + var maybePromise = tryConvertToPromise(thenable); + if (maybePromise !== thenable && + typeof thenable._isDisposable === "function" && + typeof thenable._getDisposer === "function" && + thenable._isDisposable()) { + maybePromise._setDisposable(thenable._getDisposer()); + } + return maybePromise; + } + function dispose(resources, inspection) { + var i = 0; + var len = resources.length; + var ret = new Promise(INTERNAL); + function iterator() { + if (i >= len) return ret._fulfill(); + var maybePromise = castPreservingDisposable(resources[i++]); + if (maybePromise instanceof Promise && + maybePromise._isDisposable()) { + try { + maybePromise = tryConvertToPromise( + maybePromise._getDisposer().tryDispose(inspection), + resources.promise); + } catch (e) { + return thrower(e); + } + if (maybePromise instanceof Promise) { + return maybePromise._then(iterator, thrower, + null, null, null); + } + } + iterator(); + } + iterator(); + return ret; + } + + function Disposer(data, promise, context) { + this._data = data; + this._promise = promise; + this._context = context; + } + + Disposer.prototype.data = function () { + return this._data; + }; + + Disposer.prototype.promise = function () { + return this._promise; + }; + + Disposer.prototype.resource = function () { + if (this.promise().isFulfilled()) { + return this.promise().value(); + } + return NULL; + }; + + Disposer.prototype.tryDispose = function(inspection) { + var resource = this.resource(); + var context = this._context; + if (context !== undefined) context._pushContext(); + var ret = resource !== NULL + ? this.doDispose(resource, inspection) : null; + if (context !== undefined) context._popContext(); + this._promise._unsetDisposable(); + this._data = null; + return ret; + }; + + Disposer.isDisposer = function (d) { + return (d != null && + typeof d.resource === "function" && + typeof d.tryDispose === "function"); + }; + + function FunctionDisposer(fn, promise, context) { + this.constructor$(fn, promise, context); + } + inherits(FunctionDisposer, Disposer); + + FunctionDisposer.prototype.doDispose = function (resource, inspection) { + var fn = this.data(); + return fn.call(resource, resource, inspection); + }; + + function maybeUnwrapDisposer(value) { + if (Disposer.isDisposer(value)) { + this.resources[this.index]._setDisposable(value); + return value.promise(); + } + return value; + } + + function ResourceList(length) { + this.length = length; + this.promise = null; + this[length-1] = null; + } + + ResourceList.prototype._resultCancelled = function() { + var len = this.length; + for (var i = 0; i < len; ++i) { + var item = this[i]; + if (item instanceof Promise) { + item.cancel(); + } + } + }; + + Promise.using = function () { + var len = arguments.length; + if (len < 2) return apiRejection( + "you must pass at least 2 arguments to Promise.using"); + var fn = arguments[len - 1]; + if (typeof fn !== "function") { + return apiRejection("expecting a function but got " + util.classString(fn)); + } + var input; + var spreadArgs = true; + if (len === 2 && Array.isArray(arguments[0])) { + input = arguments[0]; + len = input.length; + spreadArgs = false; + } else { + input = arguments; + len--; + } + var resources = new ResourceList(len); + for (var i = 0; i < len; ++i) { + var resource = input[i]; + if (Disposer.isDisposer(resource)) { + var disposer = resource; + resource = resource.promise(); + resource._setDisposable(disposer); + } else { + var maybePromise = tryConvertToPromise(resource); + if (maybePromise instanceof Promise) { + resource = + maybePromise._then(maybeUnwrapDisposer, null, null, { + resources: resources, + index: i + }, undefined); + } + } + resources[i] = resource; + } + + var reflectedResources = new Array(resources.length); + for (var i = 0; i < reflectedResources.length; ++i) { + reflectedResources[i] = Promise.resolve(resources[i]).reflect(); + } + + var resultPromise = Promise.all(reflectedResources) + .then(function(inspections) { + for (var i = 0; i < inspections.length; ++i) { + var inspection = inspections[i]; + if (inspection.isRejected()) { + errorObj.e = inspection.error(); + return errorObj; + } else if (!inspection.isFulfilled()) { + resultPromise.cancel(); + return; + } + inspections[i] = inspection.value(); + } + promise._pushContext(); + + fn = tryCatch(fn); + var ret = spreadArgs + ? fn.apply(undefined, inspections) : fn(inspections); + var promiseCreated = promise._popContext(); + debug.checkForgottenReturns( + ret, promiseCreated, "Promise.using", promise); + return ret; + }); + + var promise = resultPromise.lastly(function() { + var inspection = new Promise.PromiseInspection(resultPromise); + return dispose(resources, inspection); + }); + resources.promise = promise; + promise._setOnCancel(resources); + return promise; + }; + + Promise.prototype._setDisposable = function (disposer) { + this._bitField = this._bitField | 131072; + this._disposer = disposer; + }; + + Promise.prototype._isDisposable = function () { + return (this._bitField & 131072) > 0; + }; + + Promise.prototype._getDisposer = function () { + return this._disposer; + }; + + Promise.prototype._unsetDisposable = function () { + this._bitField = this._bitField & (~131072); + this._disposer = undefined; + }; + + Promise.prototype.disposer = function (fn) { + if (typeof fn === "function") { + return new FunctionDisposer(fn, this, createContext()); + } + throw new TypeError(); + }; + +}; + +},{"./errors":12,"./util":36}],36:[function(_dereq_,module,exports){ +"use strict"; +var es5 = _dereq_("./es5"); +var canEvaluate = typeof navigator == "undefined"; + +var errorObj = {e: {}}; +var tryCatchTarget; +var globalObject = typeof self !== "undefined" ? self : + typeof window !== "undefined" ? window : + typeof global !== "undefined" ? global : + this !== undefined ? this : null; + +function tryCatcher() { + try { + var target = tryCatchTarget; + tryCatchTarget = null; + return target.apply(this, arguments); + } catch (e) { + errorObj.e = e; + return errorObj; + } +} +function tryCatch(fn) { + tryCatchTarget = fn; + return tryCatcher; +} + +var inherits = function(Child, Parent) { + var hasProp = {}.hasOwnProperty; + + function T() { + this.constructor = Child; + this.constructor$ = Parent; + for (var propertyName in Parent.prototype) { + if (hasProp.call(Parent.prototype, propertyName) && + propertyName.charAt(propertyName.length-1) !== "$" + ) { + this[propertyName + "$"] = Parent.prototype[propertyName]; + } + } + } + T.prototype = Parent.prototype; + Child.prototype = new T(); + return Child.prototype; +}; + + +function isPrimitive(val) { + return val == null || val === true || val === false || + typeof val === "string" || typeof val === "number"; + +} + +function isObject(value) { + return typeof value === "function" || + typeof value === "object" && value !== null; +} + +function maybeWrapAsError(maybeError) { + if (!isPrimitive(maybeError)) return maybeError; + + return new Error(safeToString(maybeError)); +} + +function withAppended(target, appendee) { + var len = target.length; + var ret = new Array(len + 1); + var i; + for (i = 0; i < len; ++i) { + ret[i] = target[i]; + } + ret[i] = appendee; + return ret; +} + +function getDataPropertyOrDefault(obj, key, defaultValue) { + if (es5.isES5) { + var desc = Object.getOwnPropertyDescriptor(obj, key); + + if (desc != null) { + return desc.get == null && desc.set == null + ? desc.value + : defaultValue; + } + } else { + return {}.hasOwnProperty.call(obj, key) ? obj[key] : undefined; + } +} + +function notEnumerableProp(obj, name, value) { + if (isPrimitive(obj)) return obj; + var descriptor = { + value: value, + configurable: true, + enumerable: false, + writable: true + }; + es5.defineProperty(obj, name, descriptor); + return obj; +} + +function thrower(r) { + throw r; +} + +var inheritedDataKeys = (function() { + var excludedPrototypes = [ + Array.prototype, + Object.prototype, + Function.prototype + ]; + + var isExcludedProto = function(val) { + for (var i = 0; i < excludedPrototypes.length; ++i) { + if (excludedPrototypes[i] === val) { + return true; + } + } + return false; + }; + + if (es5.isES5) { + var getKeys = Object.getOwnPropertyNames; + return function(obj) { + var ret = []; + var visitedKeys = Object.create(null); + while (obj != null && !isExcludedProto(obj)) { + var keys; + try { + keys = getKeys(obj); + } catch (e) { + return ret; + } + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (visitedKeys[key]) continue; + visitedKeys[key] = true; + var desc = Object.getOwnPropertyDescriptor(obj, key); + if (desc != null && desc.get == null && desc.set == null) { + ret.push(key); + } + } + obj = es5.getPrototypeOf(obj); + } + return ret; + }; + } else { + var hasProp = {}.hasOwnProperty; + return function(obj) { + if (isExcludedProto(obj)) return []; + var ret = []; + + /*jshint forin:false */ + enumeration: for (var key in obj) { + if (hasProp.call(obj, key)) { + ret.push(key); + } else { + for (var i = 0; i < excludedPrototypes.length; ++i) { + if (hasProp.call(excludedPrototypes[i], key)) { + continue enumeration; + } + } + ret.push(key); + } + } + return ret; + }; + } + +})(); + +var thisAssignmentPattern = /this\s*\.\s*\S+\s*=/; +function isClass(fn) { + try { + if (typeof fn === "function") { + var keys = es5.names(fn.prototype); + + var hasMethods = es5.isES5 && keys.length > 1; + var hasMethodsOtherThanConstructor = keys.length > 0 && + !(keys.length === 1 && keys[0] === "constructor"); + var hasThisAssignmentAndStaticMethods = + thisAssignmentPattern.test(fn + "") && es5.names(fn).length > 0; + + if (hasMethods || hasMethodsOtherThanConstructor || + hasThisAssignmentAndStaticMethods) { + return true; + } + } + return false; + } catch (e) { + return false; + } +} + +function toFastProperties(obj) { + /*jshint -W027,-W055,-W031*/ + function FakeConstructor() {} + FakeConstructor.prototype = obj; + var receiver = new FakeConstructor(); + function ic() { + return typeof receiver.foo; + } + ic(); + ic(); + return obj; + eval(obj); +} + +var rident = /^[a-z$_][a-z$_0-9]*$/i; +function isIdentifier(str) { + return rident.test(str); +} + +function filledRange(count, prefix, suffix) { + var ret = new Array(count); + for(var i = 0; i < count; ++i) { + ret[i] = prefix + i + suffix; + } + return ret; +} + +function safeToString(obj) { + try { + return obj + ""; + } catch (e) { + return "[no string representation]"; + } +} + +function isError(obj) { + return obj instanceof Error || + (obj !== null && + typeof obj === "object" && + typeof obj.message === "string" && + typeof obj.name === "string"); +} + +function markAsOriginatingFromRejection(e) { + try { + notEnumerableProp(e, "isOperational", true); + } + catch(ignore) {} +} + +function originatesFromRejection(e) { + if (e == null) return false; + return ((e instanceof Error["__BluebirdErrorTypes__"].OperationalError) || + e["isOperational"] === true); +} + +function canAttachTrace(obj) { + return isError(obj) && es5.propertyIsWritable(obj, "stack"); +} + +var ensureErrorObject = (function() { + if (!("stack" in new Error())) { + return function(value) { + if (canAttachTrace(value)) return value; + try {throw new Error(safeToString(value));} + catch(err) {return err;} + }; + } else { + return function(value) { + if (canAttachTrace(value)) return value; + return new Error(safeToString(value)); + }; + } +})(); + +function classString(obj) { + return {}.toString.call(obj); +} + +function copyDescriptors(from, to, filter) { + var keys = es5.names(from); + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (filter(key)) { + try { + es5.defineProperty(to, key, es5.getDescriptor(from, key)); + } catch (ignore) {} + } + } +} + +var asArray = function(v) { + if (es5.isArray(v)) { + return v; + } + return null; +}; + +if (typeof Symbol !== "undefined" && Symbol.iterator) { + var ArrayFrom = typeof Array.from === "function" ? function(v) { + return Array.from(v); + } : function(v) { + var ret = []; + var it = v[Symbol.iterator](); + var itResult; + while (!((itResult = it.next()).done)) { + ret.push(itResult.value); + } + return ret; + }; + + asArray = function(v) { + if (es5.isArray(v)) { + return v; + } else if (v != null && typeof v[Symbol.iterator] === "function") { + return ArrayFrom(v); + } + return null; + }; +} + +var isNode = typeof process !== "undefined" && + classString(process).toLowerCase() === "[object process]"; + +var hasEnvVariables = typeof process !== "undefined" && + typeof process.env !== "undefined"; + +function env(key) { + return hasEnvVariables ? process.env[key] : undefined; +} + +function getNativePromise() { + if (typeof Promise === "function") { + try { + var promise = new Promise(function(){}); + if ({}.toString.call(promise) === "[object Promise]") { + return Promise; + } + } catch (e) {} + } +} + +function domainBind(self, cb) { + return self.bind(cb); +} + +var ret = { + isClass: isClass, + isIdentifier: isIdentifier, + inheritedDataKeys: inheritedDataKeys, + getDataPropertyOrDefault: getDataPropertyOrDefault, + thrower: thrower, + isArray: es5.isArray, + asArray: asArray, + notEnumerableProp: notEnumerableProp, + isPrimitive: isPrimitive, + isObject: isObject, + isError: isError, + canEvaluate: canEvaluate, + errorObj: errorObj, + tryCatch: tryCatch, + inherits: inherits, + withAppended: withAppended, + maybeWrapAsError: maybeWrapAsError, + toFastProperties: toFastProperties, + filledRange: filledRange, + toString: safeToString, + canAttachTrace: canAttachTrace, + ensureErrorObject: ensureErrorObject, + originatesFromRejection: originatesFromRejection, + markAsOriginatingFromRejection: markAsOriginatingFromRejection, + classString: classString, + copyDescriptors: copyDescriptors, + hasDevTools: typeof chrome !== "undefined" && chrome && + typeof chrome.loadTimes === "function", + isNode: isNode, + hasEnvVariables: hasEnvVariables, + env: env, + global: globalObject, + getNativePromise: getNativePromise, + domainBind: domainBind +}; +ret.isRecentNode = ret.isNode && (function() { + var version = process.versions.node.split(".").map(Number); + return (version[0] === 0 && version[1] > 10) || (version[0] > 0); +})(); + +if (ret.isNode) ret.toFastProperties(process); + +try {throw new Error(); } catch (e) {ret.lastLineError = e;} +module.exports = ret; + +},{"./es5":13}]},{},[4])(4) +}); ;if (typeof window !== 'undefined' && window !== null) { window.P = window.Promise; } else if (typeof self !== 'undefined' && self !== null) { self.P = self.Promise; } \ No newline at end of file diff --git a/express-server/node_modules/bluebird/js/browser/bluebird.min.js b/express-server/node_modules/bluebird/js/browser/bluebird.min.js new file mode 100644 index 00000000..23bc16d5 --- /dev/null +++ b/express-server/node_modules/bluebird/js/browser/bluebird.min.js @@ -0,0 +1,31 @@ +/* @preserve + * The MIT License (MIT) + * + * Copyright (c) 2013-2018 Petka Antonov + * + * 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. + * + */ +/** + * bluebird build version 3.5.3 + * Features enabled: core, race, call_get, generators, map, nodeify, promisify, props, reduce, settle, some, using, timers, filter, any, each +*/ +!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;"undefined"!=typeof window?e=window:"undefined"!=typeof global?e=global:"undefined"!=typeof self&&(e=self),e.Promise=t()}}(function(){var t,e,n;return function r(t,e,n){function i(s,a){if(!e[s]){if(!t[s]){var c="function"==typeof _dereq_&&_dereq_;if(!a&&c)return c(s,!0);if(o)return o(s,!0);var l=new Error("Cannot find module '"+s+"'");throw l.code="MODULE_NOT_FOUND",l}var u=e[s]={exports:{}};t[s][0].call(u.exports,function(e){var n=t[s][1][e];return i(n?n:e)},u,u.exports,r,t,e,n)}return e[s].exports}for(var o="function"==typeof _dereq_&&_dereq_,s=0;s0;)c(t)}function c(t){var e=t.shift();if("function"!=typeof e)e._settlePromises();else{var n=t.shift(),r=t.shift();e.call(n,r)}}var l;try{throw new Error}catch(u){l=u}var p=t("./schedule"),h=t("./queue"),f=t("./util");r.prototype.setScheduler=function(t){var e=this._schedule;return this._schedule=t,this._customScheduler=!0,e},r.prototype.hasCustomScheduler=function(){return this._customScheduler},r.prototype.enableTrampoline=function(){this._trampolineEnabled=!0},r.prototype.disableTrampolineIfNecessary=function(){f.hasDevTools&&(this._trampolineEnabled=!1)},r.prototype.haveItemsQueued=function(){return this._isTickUsed||this._haveDrainedQueues},r.prototype.fatalError=function(t,e){e?(process.stderr.write("Fatal "+(t instanceof Error?t.stack:t)+"\n"),process.exit(2)):this.throwLater(t)},r.prototype.throwLater=function(t,e){if(1===arguments.length&&(e=t,t=function(){throw e}),"undefined"!=typeof setTimeout)setTimeout(function(){t(e)},0);else try{this._schedule(function(){t(e)})}catch(n){throw new Error("No async scheduler available\n\n See http://goo.gl/MqrFmX\n")}},f.hasDevTools?(r.prototype.invokeLater=function(t,e,n){this._trampolineEnabled?i.call(this,t,e,n):this._schedule(function(){setTimeout(function(){t.call(e,n)},100)})},r.prototype.invoke=function(t,e,n){this._trampolineEnabled?o.call(this,t,e,n):this._schedule(function(){t.call(e,n)})},r.prototype.settlePromises=function(t){this._trampolineEnabled?s.call(this,t):this._schedule(function(){t._settlePromises()})}):(r.prototype.invokeLater=i,r.prototype.invoke=o,r.prototype.settlePromises=s),r.prototype._drainQueues=function(){a(this._normalQueue),this._reset(),this._haveDrainedQueues=!0,a(this._lateQueue)},r.prototype._queueTick=function(){this._isTickUsed||(this._isTickUsed=!0,this._schedule(this.drainQueues))},r.prototype._reset=function(){this._isTickUsed=!1},e.exports=r,e.exports.firstLineError=l},{"./queue":26,"./schedule":29,"./util":36}],3:[function(t,e,n){"use strict";e.exports=function(t,e,n,r){var i=!1,o=function(t,e){this._reject(e)},s=function(t,e){e.promiseRejectionQueued=!0,e.bindingPromise._then(o,o,null,this,t)},a=function(t,e){0===(50397184&this._bitField)&&this._resolveCallback(e.target)},c=function(t,e){e.promiseRejectionQueued||this._reject(t)};t.prototype.bind=function(o){i||(i=!0,t.prototype._propagateFrom=r.propagateFromFunction(),t.prototype._boundValue=r.boundValueFunction());var l=n(o),u=new t(e);u._propagateFrom(this,1);var p=this._target();if(u._setBoundTo(l),l instanceof t){var h={promiseRejectionQueued:!1,promise:u,target:p,bindingPromise:l};p._then(e,s,void 0,u,h),l._then(a,c,void 0,u,h),u._setOnCancel(l)}else u._resolveCallback(p);return u},t.prototype._setBoundTo=function(t){void 0!==t?(this._bitField=2097152|this._bitField,this._boundTo=t):this._bitField=-2097153&this._bitField},t.prototype._isBound=function(){return 2097152===(2097152&this._bitField)},t.bind=function(e,n){return t.resolve(n).bind(e)}}},{}],4:[function(t,e,n){"use strict";function r(){try{Promise===o&&(Promise=i)}catch(t){}return o}var i;"undefined"!=typeof Promise&&(i=Promise);var o=t("./promise")();o.noConflict=r,e.exports=o},{"./promise":22}],5:[function(t,e,n){"use strict";var r=Object.create;if(r){var i=r(null),o=r(null);i[" size"]=o[" size"]=0}e.exports=function(e){function n(t,n){var r;if(null!=t&&(r=t[n]),"function"!=typeof r){var i="Object "+a.classString(t)+" has no method '"+a.toString(n)+"'";throw new e.TypeError(i)}return r}function r(t){var e=this.pop(),r=n(t,e);return r.apply(t,this)}function i(t){return t[this]}function o(t){var e=+this;return 0>e&&(e=Math.max(0,e+t.length)),t[e]}var s,a=t("./util"),c=a.canEvaluate;a.isIdentifier;e.prototype.call=function(t){var e=[].slice.call(arguments,1);return e.push(t),this._then(r,void 0,void 0,e,void 0)},e.prototype.get=function(t){var e,n="number"==typeof t;if(n)e=o;else if(c){var r=s(t);e=null!==r?r:i}else e=i;return this._then(e,void 0,void 0,t,void 0)}}},{"./util":36}],6:[function(t,e,n){"use strict";e.exports=function(e,n,r,i){var o=t("./util"),s=o.tryCatch,a=o.errorObj,c=e._async;e.prototype["break"]=e.prototype.cancel=function(){if(!i.cancellation())return this._warn("cancellation is disabled");for(var t=this,e=t;t._isCancellable();){if(!t._cancelBy(e)){e._isFollowing()?e._followee().cancel():e._cancelBranched();break}var n=t._cancellationParent;if(null==n||!n._isCancellable()){t._isFollowing()?t._followee().cancel():t._cancelBranched();break}t._isFollowing()&&t._followee().cancel(),t._setWillBeCancelled(),e=t,t=n}},e.prototype._branchHasCancelled=function(){this._branchesRemainingToCancel--},e.prototype._enoughBranchesHaveCancelled=function(){return void 0===this._branchesRemainingToCancel||this._branchesRemainingToCancel<=0},e.prototype._cancelBy=function(t){return t===this?(this._branchesRemainingToCancel=0,this._invokeOnCancel(),!0):(this._branchHasCancelled(),this._enoughBranchesHaveCancelled()?(this._invokeOnCancel(),!0):!1)},e.prototype._cancelBranched=function(){this._enoughBranchesHaveCancelled()&&this._cancel()},e.prototype._cancel=function(){this._isCancellable()&&(this._setCancelled(),c.invoke(this._cancelPromises,this,void 0))},e.prototype._cancelPromises=function(){this._length()>0&&this._settlePromises()},e.prototype._unsetOnCancel=function(){this._onCancelField=void 0},e.prototype._isCancellable=function(){return this.isPending()&&!this._isCancelled()},e.prototype.isCancellable=function(){return this.isPending()&&!this.isCancelled()},e.prototype._doInvokeOnCancel=function(t,e){if(o.isArray(t))for(var n=0;n=0?o[t]:void 0}var i=!1,o=[];return t.prototype._promiseCreated=function(){},t.prototype._pushContext=function(){},t.prototype._popContext=function(){return null},t._peekContext=t.prototype._peekContext=function(){},e.prototype._pushContext=function(){void 0!==this._trace&&(this._trace._promiseCreated=null,o.push(this._trace))},e.prototype._popContext=function(){if(void 0!==this._trace){var t=o.pop(),e=t._promiseCreated;return t._promiseCreated=null,e}return null},e.CapturedTrace=null,e.create=n,e.deactivateLongStackTraces=function(){},e.activateLongStackTraces=function(){var n=t.prototype._pushContext,o=t.prototype._popContext,s=t._peekContext,a=t.prototype._peekContext,c=t.prototype._promiseCreated;e.deactivateLongStackTraces=function(){t.prototype._pushContext=n,t.prototype._popContext=o,t._peekContext=s,t.prototype._peekContext=a,t.prototype._promiseCreated=c,i=!1},i=!0,t.prototype._pushContext=e.prototype._pushContext,t.prototype._popContext=e.prototype._popContext,t._peekContext=t.prototype._peekContext=r,t.prototype._promiseCreated=function(){var t=this._peekContext();t&&null==t._promiseCreated&&(t._promiseCreated=this)}},e}},{}],9:[function(t,e,n){"use strict";e.exports=function(e,n){function r(t,e){return{promise:e}}function i(){return!1}function o(t,e,n){var r=this;try{t(e,n,function(t){if("function"!=typeof t)throw new TypeError("onCancel must be a function, got: "+N.toString(t));r._attachCancellationCallback(t)})}catch(i){return i}}function s(t){if(!this._isCancellable())return this;var e=this._onCancel();void 0!==e?N.isArray(e)?e.push(t):this._setOnCancel([e,t]):this._setOnCancel(t)}function a(){return this._onCancelField}function c(t){this._onCancelField=t}function l(){this._cancellationParent=void 0,this._onCancelField=void 0}function u(t,e){if(0!==(1&e)){this._cancellationParent=t;var n=t._branchesRemainingToCancel;void 0===n&&(n=0),t._branchesRemainingToCancel=n+1}0!==(2&e)&&t._isBound()&&this._setBoundTo(t._boundTo)}function p(t,e){0!==(2&e)&&t._isBound()&&this._setBoundTo(t._boundTo)}function h(){var t=this._boundTo;return void 0!==t&&t instanceof e?t.isFulfilled()?t.value():void 0:t}function f(){this._trace=new O(this._peekContext())}function _(t,e){if(U(t)){var n=this._trace;if(void 0!==n&&e&&(n=n._parent),void 0!==n)n.attachExtraTrace(t);else if(!t.__stackCleaned__){var r=E(t);N.notEnumerableProp(t,"stack",r.message+"\n"+r.stack.join("\n")),N.notEnumerableProp(t,"__stackCleaned__",!0)}}}function d(){this._trace=void 0}function v(t,e,n,r,i){if(void 0===t&&null!==e&&J){if(void 0!==i&&i._returnedNonUndefined())return;if(0===(65535&r._bitField))return;n&&(n+=" ");var o="",s="";if(e._trace){for(var a=e._trace.stack.split("\n"),c=C(a),l=c.length-1;l>=0;--l){var u=c[l];if(!q.test(u)){var p=u.match($);p&&(o="at "+p[1]+":"+p[2]+":"+p[3]+" ");break}}if(c.length>0)for(var h=c[0],l=0;l0&&(s="\n"+a[l-1]);break}}var f="a promise was created in a "+n+"handler "+o+"but was not returned from it, see http://goo.gl/rRqMUw"+s;r._warn(f,!0,e)}}function y(t,e){var n=t+" is deprecated and will be removed in a future version.";return e&&(n+=" Use "+e+" instead."),m(n)}function m(t,n,r){if(at.warnings){var i,o=new H(t);if(n)r._attachExtraTrace(o);else if(at.longStackTraces&&(i=e._peekContext()))i.attachExtraTrace(o);else{var s=E(o);o.stack=s.message+"\n"+s.stack.join("\n")}nt("warning",o)||k(o,"",!0)}}function g(t,e){for(var n=0;n=0;--a)if(r[a]===o){s=a;break}for(var a=s;a>=0;--a){var c=r[a];if(e[i]!==c)break;e.pop(),i--}e=r}}function C(t){for(var e=[],n=0;n0&&"SyntaxError"!=t.name&&(e=e.slice(n)),e}function E(t){var e=t.stack,n=t.toString();return e="string"==typeof e&&e.length>0?j(t):[" (No stack trace)"],{message:n,stack:"SyntaxError"==t.name?e:C(e)}}function k(t,e,n){if("undefined"!=typeof console){var r;if(N.isObject(t)){var i=t.stack;r=e+G(i,t)}else r=e+String(t);"function"==typeof V?V(r,n):("function"==typeof console.log||"object"==typeof console.log)&&console.log(r)}}function F(t,e,n,r){var i=!1;try{"function"==typeof e&&(i=!0,"rejectionHandled"===t?e(r):e(n,r))}catch(o){L.throwLater(o)}"unhandledRejection"===t?nt(t,n,r)||i||k(n,"Unhandled rejection "):nt(t,r)}function T(t){var e;if("function"==typeof t)e="[function "+(t.name||"anonymous")+"]";else{e=t&&"function"==typeof t.toString?t.toString():N.toString(t);var n=/\[object [a-zA-Z0-9$_]+\]/;if(n.test(e))try{var r=JSON.stringify(t);e=r}catch(i){}0===e.length&&(e="(empty array)")}return"(<"+x(e)+">, no stack trace)"}function x(t){var e=41;return t.lengths||0>a||!n||!r||n!==r||s>=a||(it=function(t){if(M.test(t))return!0;var e=R(t);return e&&e.fileName===n&&s<=e.line&&e.line<=a?!0:!1})}}function O(t){this._parent=t,this._promisesCreated=0;var e=this._length=1+(void 0===t?0:t._length);st(this,O),e>32&&this.uncycle()}var A,D,V,I=e._getDomain,L=e._async,H=t("./errors").Warning,N=t("./util"),B=t("./es5"),U=N.canAttachTrace,M=/[\\\/]bluebird[\\\/]js[\\\/](release|debug|instrumented)/,q=/\((?:timers\.js):\d+:\d+\)/,$=/[\/<\(](.+?):(\d+):(\d+)\)?\s*$/,Q=null,G=null,z=!1,X=!(0==N.env("BLUEBIRD_DEBUG")||!N.env("BLUEBIRD_DEBUG")&&"development"!==N.env("NODE_ENV")),W=!(0==N.env("BLUEBIRD_WARNINGS")||!X&&!N.env("BLUEBIRD_WARNINGS")),K=!(0==N.env("BLUEBIRD_LONG_STACK_TRACES")||!X&&!N.env("BLUEBIRD_LONG_STACK_TRACES")),J=0!=N.env("BLUEBIRD_W_FORGOTTEN_RETURN")&&(W||!!N.env("BLUEBIRD_W_FORGOTTEN_RETURN"));e.prototype.suppressUnhandledRejections=function(){var t=this._target();t._bitField=-1048577&t._bitField|524288},e.prototype._ensurePossibleRejectionHandled=function(){if(0===(524288&this._bitField)){this._setRejectionIsUnhandled();var t=this;setTimeout(function(){t._notifyUnhandledRejection()},1)}},e.prototype._notifyUnhandledRejectionIsHandled=function(){F("rejectionHandled",A,void 0,this)},e.prototype._setReturnedNonUndefined=function(){this._bitField=268435456|this._bitField},e.prototype._returnedNonUndefined=function(){return 0!==(268435456&this._bitField)},e.prototype._notifyUnhandledRejection=function(){if(this._isRejectionUnhandled()){var t=this._settledValue();this._setUnhandledRejectionIsNotified(),F("unhandledRejection",D,t,this)}},e.prototype._setUnhandledRejectionIsNotified=function(){this._bitField=262144|this._bitField},e.prototype._unsetUnhandledRejectionIsNotified=function(){this._bitField=-262145&this._bitField},e.prototype._isUnhandledRejectionNotified=function(){return(262144&this._bitField)>0},e.prototype._setRejectionIsUnhandled=function(){this._bitField=1048576|this._bitField},e.prototype._unsetRejectionIsUnhandled=function(){this._bitField=-1048577&this._bitField,this._isUnhandledRejectionNotified()&&(this._unsetUnhandledRejectionIsNotified(),this._notifyUnhandledRejectionIsHandled())},e.prototype._isRejectionUnhandled=function(){return(1048576&this._bitField)>0},e.prototype._warn=function(t,e,n){return m(t,e,n||this)},e.onPossiblyUnhandledRejection=function(t){var e=I();D="function"==typeof t?null===e?t:N.domainBind(e,t):void 0},e.onUnhandledRejectionHandled=function(t){var e=I();A="function"==typeof t?null===e?t:N.domainBind(e,t):void 0};var Y=function(){};e.longStackTraces=function(){if(L.haveItemsQueued()&&!at.longStackTraces)throw new Error("cannot enable long stack traces after promises have been created\n\n See http://goo.gl/MqrFmX\n");if(!at.longStackTraces&&P()){var t=e.prototype._captureStackTrace,r=e.prototype._attachExtraTrace,i=e.prototype._dereferenceTrace;at.longStackTraces=!0,Y=function(){if(L.haveItemsQueued()&&!at.longStackTraces)throw new Error("cannot enable long stack traces after promises have been created\n\n See http://goo.gl/MqrFmX\n");e.prototype._captureStackTrace=t,e.prototype._attachExtraTrace=r,e.prototype._dereferenceTrace=i,n.deactivateLongStackTraces(),L.enableTrampoline(),at.longStackTraces=!1},e.prototype._captureStackTrace=f,e.prototype._attachExtraTrace=_,e.prototype._dereferenceTrace=d,n.activateLongStackTraces(),L.disableTrampolineIfNecessary()}},e.hasLongStackTraces=function(){return at.longStackTraces&&P()};var Z=function(){try{if("function"==typeof CustomEvent){var t=new CustomEvent("CustomEvent");return N.global.dispatchEvent(t),function(t,e){var n={detail:e,cancelable:!0};B.defineProperty(n,"promise",{value:e.promise}),B.defineProperty(n,"reason",{value:e.reason});var r=new CustomEvent(t.toLowerCase(),n);return!N.global.dispatchEvent(r)}}if("function"==typeof Event){var t=new Event("CustomEvent");return N.global.dispatchEvent(t),function(t,e){var n=new Event(t.toLowerCase(),{cancelable:!0});return n.detail=e,B.defineProperty(n,"promise",{value:e.promise}),B.defineProperty(n,"reason",{value:e.reason}),!N.global.dispatchEvent(n)}}var t=document.createEvent("CustomEvent");return t.initCustomEvent("testingtheevent",!1,!0,{}),N.global.dispatchEvent(t),function(t,e){var n=document.createEvent("CustomEvent");return n.initCustomEvent(t.toLowerCase(),!1,!0,e),!N.global.dispatchEvent(n)}}catch(e){}return function(){return!1}}(),tt=function(){return N.isNode?function(){return process.emit.apply(process,arguments)}:N.global?function(t){var e="on"+t.toLowerCase(),n=N.global[e];return n?(n.apply(N.global,[].slice.call(arguments,1)),!0):!1}:function(){return!1}}(),et={promiseCreated:r,promiseFulfilled:r,promiseRejected:r,promiseResolved:r,promiseCancelled:r,promiseChained:function(t,e,n){return{promise:e,child:n}},warning:function(t,e){return{warning:e}},unhandledRejection:function(t,e,n){return{reason:e,promise:n}},rejectionHandled:r},nt=function(t){var e=!1;try{e=tt.apply(null,arguments)}catch(n){L.throwLater(n),e=!0}var r=!1;try{r=Z(t,et[t].apply(null,arguments))}catch(n){L.throwLater(n),r=!0}return r||e};e.config=function(t){if(t=Object(t),"longStackTraces"in t&&(t.longStackTraces?e.longStackTraces():!t.longStackTraces&&e.hasLongStackTraces()&&Y()),"warnings"in t){var n=t.warnings;at.warnings=!!n,J=at.warnings,N.isObject(n)&&"wForgottenReturn"in n&&(J=!!n.wForgottenReturn)}if("cancellation"in t&&t.cancellation&&!at.cancellation){if(L.haveItemsQueued())throw new Error("cannot enable cancellation after promises are in use");e.prototype._clearCancellationData=l,e.prototype._propagateFrom=u,e.prototype._onCancel=a,e.prototype._setOnCancel=c,e.prototype._attachCancellationCallback=s,e.prototype._execute=o,rt=u,at.cancellation=!0}return"monitoring"in t&&(t.monitoring&&!at.monitoring?(at.monitoring=!0,e.prototype._fireEvent=nt):!t.monitoring&&at.monitoring&&(at.monitoring=!1,e.prototype._fireEvent=i)),e},e.prototype._fireEvent=i,e.prototype._execute=function(t,e,n){try{t(e,n)}catch(r){return r}},e.prototype._onCancel=function(){},e.prototype._setOnCancel=function(t){},e.prototype._attachCancellationCallback=function(t){},e.prototype._captureStackTrace=function(){},e.prototype._attachExtraTrace=function(){},e.prototype._dereferenceTrace=function(){},e.prototype._clearCancellationData=function(){},e.prototype._propagateFrom=function(t,e){};var rt=p,it=function(){return!1},ot=/[\/<\(]([^:\/]+):(\d+):(?:\d+)\)?\s*$/;N.inherits(O,Error),n.CapturedTrace=O,O.prototype.uncycle=function(){var t=this._length;if(!(2>t)){for(var e=[],n={},r=0,i=this;void 0!==i;++r)e.push(i),i=i._parent;t=this._length=r;for(var r=t-1;r>=0;--r){var o=e[r].stack;void 0===n[o]&&(n[o]=r)}for(var r=0;t>r;++r){var s=e[r].stack,a=n[s];if(void 0!==a&&a!==r){a>0&&(e[a-1]._parent=void 0,e[a-1]._length=1),e[r]._parent=void 0,e[r]._length=1;var c=r>0?e[r-1]:this;t-1>a?(c._parent=e[a+1],c._parent.uncycle(),c._length=c._parent._length+1):(c._parent=void 0,c._length=1);for(var l=c._length+1,u=r-2;u>=0;--u)e[u]._length=l,l++;return}}}},O.prototype.attachExtraTrace=function(t){if(!t.__stackCleaned__){this.uncycle();for(var e=E(t),n=e.message,r=[e.stack],i=this;void 0!==i;)r.push(C(i.stack.split("\n"))),i=i._parent;w(r),b(r),N.notEnumerableProp(t,"stack",g(n,r)),N.notEnumerableProp(t,"__stackCleaned__",!0)}};var st=function(){var t=/^\s*at\s*/,e=function(t,e){return"string"==typeof t?t:void 0!==e.name&&void 0!==e.message?e.toString():T(e)};if("number"==typeof Error.stackTraceLimit&&"function"==typeof Error.captureStackTrace){Error.stackTraceLimit+=6,Q=t,G=e;var n=Error.captureStackTrace;return it=function(t){return M.test(t)},function(t,e){Error.stackTraceLimit+=6,n(t,e),Error.stackTraceLimit-=6}}var r=new Error;if("string"==typeof r.stack&&r.stack.split("\n")[0].indexOf("stackDetection@")>=0)return Q=/@/,G=e,z=!0,function(t){t.stack=(new Error).stack};var i;try{throw new Error}catch(o){i="stack"in o}return"stack"in r||!i||"number"!=typeof Error.stackTraceLimit?(G=function(t,e){return"string"==typeof t?t:"object"!=typeof e&&"function"!=typeof e||void 0===e.name||void 0===e.message?T(e):e.toString()},null):(Q=t,G=e,function(t){Error.stackTraceLimit+=6;try{throw new Error}catch(e){t.stack=e.stack}Error.stackTraceLimit-=6})}([]);"undefined"!=typeof console&&"undefined"!=typeof console.warn&&(V=function(t){console.warn(t)},N.isNode&&process.stderr.isTTY?V=function(t,e){var n=e?"":"";console.warn(n+t+"\n")}:N.isNode||"string"!=typeof(new Error).stack||(V=function(t,e){console.warn("%c"+t,e?"color: darkorange":"color: red")}));var at={warnings:W,longStackTraces:!1,cancellation:!1,monitoring:!1};return K&&e.longStackTraces(),{longStackTraces:function(){return at.longStackTraces},warnings:function(){return at.warnings},cancellation:function(){return at.cancellation},monitoring:function(){return at.monitoring},propagateFromFunction:function(){return rt},boundValueFunction:function(){return h},checkForgottenReturns:v,setBounds:S,warn:m,deprecated:y,CapturedTrace:O,fireDomEvent:Z,fireGlobalEvent:tt}}},{"./errors":12,"./es5":13,"./util":36}],10:[function(t,e,n){"use strict";e.exports=function(t){function e(){return this.value}function n(){throw this.reason}t.prototype["return"]=t.prototype.thenReturn=function(n){return n instanceof t&&n.suppressUnhandledRejections(),this._then(e,void 0,void 0,{value:n},void 0)},t.prototype["throw"]=t.prototype.thenThrow=function(t){return this._then(n,void 0,void 0,{reason:t},void 0)},t.prototype.catchThrow=function(t){if(arguments.length<=1)return this._then(void 0,n,void 0,{reason:t},void 0);var e=arguments[1],r=function(){throw e};return this.caught(t,r)},t.prototype.catchReturn=function(n){if(arguments.length<=1)return n instanceof t&&n.suppressUnhandledRejections(),this._then(void 0,e,void 0,{value:n},void 0);var r=arguments[1];r instanceof t&&r.suppressUnhandledRejections();var i=function(){return r};return this.caught(n,i)}}},{}],11:[function(t,e,n){"use strict";e.exports=function(t,e){function n(){return o(this)}function r(t,n){return i(t,n,e,e)}var i=t.reduce,o=t.all;t.prototype.each=function(t){return i(this,t,e,0)._then(n,void 0,void 0,this,void 0)},t.prototype.mapSeries=function(t){return i(this,t,e,e)},t.each=function(t,r){return i(t,r,e,0)._then(n,void 0,void 0,t,void 0)},t.mapSeries=r}},{}],12:[function(t,e,n){"use strict";function r(t,e){function n(r){return this instanceof n?(p(this,"message","string"==typeof r?r:e),p(this,"name",t),void(Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):Error.call(this))):new n(r)}return u(n,Error),n}function i(t){return this instanceof i?(p(this,"name","OperationalError"),p(this,"message",t),this.cause=t,this.isOperational=!0,void(t instanceof Error?(p(this,"message",t.message),p(this,"stack",t.stack)):Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor))):new i(t)}var o,s,a=t("./es5"),c=a.freeze,l=t("./util"),u=l.inherits,p=l.notEnumerableProp,h=r("Warning","warning"),f=r("CancellationError","cancellation error"),_=r("TimeoutError","timeout error"),d=r("AggregateError","aggregate error");try{o=TypeError,s=RangeError}catch(v){o=r("TypeError","type error"),s=r("RangeError","range error")}for(var y="join pop push shift unshift slice filter forEach some every map indexOf lastIndexOf reduce reduceRight sort reverse".split(" "),m=0;m1?t.cancelPromise._reject(e):t.cancelPromise._cancel(),t.cancelPromise=null,!0):!1}function a(){return l.call(this,this.promise._target()._settledValue())}function c(t){return s(this,t)?void 0:(h.e=t,h)}function l(t){var i=this.promise,l=this.handler;if(!this.called){this.called=!0;var u=this.isFinallyHandler()?l.call(i._boundValue()):l.call(i._boundValue(),t);if(u===r)return u;if(void 0!==u){i._setReturnedNonUndefined();var f=n(u,i);if(f instanceof e){if(null!=this.cancelPromise){if(f._isCancelled()){var _=new p("late cancellation observer");return i._attachExtraTrace(_),h.e=_,h}f.isPending()&&f._attachCancellationCallback(new o(this))}return f._then(a,c,void 0,this,void 0)}}}return i.isRejected()?(s(this),h.e=t,h):(s(this),t)}var u=t("./util"),p=e.CancellationError,h=u.errorObj,f=t("./catch_filter")(r);return i.prototype.isFinallyHandler=function(){return 0===this.type},o.prototype._resultCancelled=function(){s(this.finallyHandler)},e.prototype._passThrough=function(t,e,n,r){return"function"!=typeof t?this.then():this._then(n,r,void 0,new i(this,e,t),void 0)},e.prototype.lastly=e.prototype["finally"]=function(t){return this._passThrough(t,0,l,l)},e.prototype.tap=function(t){return this._passThrough(t,1,l)},e.prototype.tapCatch=function(t){var n=arguments.length;if(1===n)return this._passThrough(t,1,void 0,l);var r,i=new Array(n-1),o=0;for(r=0;n-1>r;++r){var s=arguments[r];if(!u.isObject(s))return e.reject(new TypeError("tapCatch statement predicate: expecting an object but got "+u.classString(s)));i[o++]=s}i.length=o;var a=arguments[r];return this._passThrough(f(i,a,this),1,void 0,l)},i}},{"./catch_filter":7,"./util":36}],16:[function(t,e,n){"use strict";e.exports=function(e,n,r,i,o,s){function a(t,n,r){for(var o=0;o0&&"function"==typeof arguments[e]){t=arguments[e];var r}var i=[].slice.call(arguments);t&&i.pop();var r=new n(i).promise();return void 0!==t?r.spread(t):r}}},{"./util":36}],18:[function(t,e,n){"use strict";e.exports=function(e,n,r,i,o,s){function a(t,e,n,r){this.constructor$(t),this._promise._captureStackTrace();var i=l();this._callback=null===i?e:u.domainBind(i,e),this._preservedValues=r===o?new Array(this.length()):null,this._limit=n,this._inFlight=0,this._queue=[],f.invoke(this._asyncInit,this,void 0)}function c(t,n,i,o){if("function"!=typeof n)return r("expecting a function but got "+u.classString(n));var s=0;if(void 0!==i){if("object"!=typeof i||null===i)return e.reject(new TypeError("options argument must be an object but it is "+u.classString(i)));if("number"!=typeof i.concurrency)return e.reject(new TypeError("'concurrency' must be a number but it is "+u.classString(i.concurrency)));s=i.concurrency}return s="number"==typeof s&&isFinite(s)&&s>=1?s:0,new a(t,n,s,o).promise()}var l=e._getDomain,u=t("./util"),p=u.tryCatch,h=u.errorObj,f=e._async;u.inherits(a,n),a.prototype._asyncInit=function(){this._init$(void 0,-2)},a.prototype._init=function(){},a.prototype._promiseFulfilled=function(t,n){var r=this._values,o=this.length(),a=this._preservedValues,c=this._limit;if(0>n){if(n=-1*n-1,r[n]=t,c>=1&&(this._inFlight--,this._drainQueue(),this._isResolved()))return!0}else{if(c>=1&&this._inFlight>=c)return r[n]=t,this._queue.push(n),!1;null!==a&&(a[n]=t);var l=this._promise,u=this._callback,f=l._boundValue();l._pushContext();var _=p(u).call(f,t,n,o),d=l._popContext();if(s.checkForgottenReturns(_,d,null!==a?"Promise.filter":"Promise.map",l),_===h)return this._reject(_.e),!0;var v=i(_,this._promise);if(v instanceof e){v=v._target();var y=v._bitField;if(0===(50397184&y))return c>=1&&this._inFlight++,r[n]=v,v._proxy(this,-1*(n+1)),!1;if(0===(33554432&y))return 0!==(16777216&y)?(this._reject(v._reason()),!0):(this._cancel(),!0);_=v._value()}r[n]=_}var m=++this._totalResolved;return m>=o?(null!==a?this._filter(r,a):this._resolve(r),!0):!1},a.prototype._drainQueue=function(){for(var t=this._queue,e=this._limit,n=this._values;t.length>0&&this._inFlighto;++o)t[o]&&(r[i++]=e[o]);r.length=i,this._resolve(r)},a.prototype.preservedValues=function(){return this._preservedValues},e.prototype.map=function(t,e){return c(this,t,e,null)},e.map=function(t,e,n,r){return c(t,e,n,r)}}},{"./util":36}],19:[function(t,e,n){"use strict";e.exports=function(e,n,r,i,o){var s=t("./util"),a=s.tryCatch;e.method=function(t){if("function"!=typeof t)throw new e.TypeError("expecting a function but got "+s.classString(t));return function(){var r=new e(n);r._captureStackTrace(),r._pushContext();var i=a(t).apply(this,arguments),s=r._popContext();return o.checkForgottenReturns(i,s,"Promise.method",r),r._resolveFromSyncValue(i),r}},e.attempt=e["try"]=function(t){if("function"!=typeof t)return i("expecting a function but got "+s.classString(t));var r=new e(n);r._captureStackTrace(),r._pushContext();var c;if(arguments.length>1){o.deprecated("calling Promise.try with more than 1 argument");var l=arguments[1],u=arguments[2];c=s.isArray(l)?a(t).apply(u,l):a(t).call(u,l)}else c=a(t)();var p=r._popContext();return o.checkForgottenReturns(c,p,"Promise.try",r),r._resolveFromSyncValue(c),r},e.prototype._resolveFromSyncValue=function(t){t===s.errorObj?this._rejectCallback(t.e,!1):this._resolveCallback(t,!0)}}},{"./util":36}],20:[function(t,e,n){"use strict";function r(t){return t instanceof Error&&u.getPrototypeOf(t)===Error.prototype}function i(t){var e;if(r(t)){e=new l(t),e.name=t.name,e.message=t.message,e.stack=t.stack;for(var n=u.keys(t),i=0;i1){var n,r=new Array(e-1),i=0;for(n=0;e-1>n;++n){var o=arguments[n];if(!f.isObject(o))return p("Catch statement predicate: expecting an object but got "+f.classString(o));r[i++]=o}return r.length=i,t=arguments[n],this.then(void 0,P(r,t,this))}return this.then(void 0,t)},i.prototype.reflect=function(){return this._then(u,u,void 0,this,void 0)},i.prototype.then=function(t,e){if(T.warnings()&&arguments.length>0&&"function"!=typeof t&&"function"!=typeof e){var n=".then() only accepts functions but was passed: "+f.classString(t);arguments.length>1&&(n+=", "+f.classString(e)),this._warn(n)}return this._then(t,e,void 0,void 0,void 0)},i.prototype.done=function(t,e){var n=this._then(t,e,void 0,void 0,void 0);n._setIsFinal()},i.prototype.spread=function(t){return"function"!=typeof t?p("expecting a function but got "+f.classString(t)):this.all()._then(t,void 0,void 0,w,void 0)},i.prototype.toJSON=function(){var t={isFulfilled:!1,isRejected:!1,fulfillmentValue:void 0,rejectionReason:void 0};return this.isFulfilled()?(t.fulfillmentValue=this.value(),t.isFulfilled=!0):this.isRejected()&&(t.rejectionReason=this.reason(),t.isRejected=!0),t},i.prototype.all=function(){return arguments.length>0&&this._warn(".all() was passed arguments but it does not take any"),new E(this).promise()},i.prototype.error=function(t){return this.caught(f.originatesFromRejection,t)},i.getNewLibraryCopy=e.exports,i.is=function(t){return t instanceof i},i.fromNode=i.fromCallback=function(t){var e=new i(b);e._captureStackTrace();var n=arguments.length>1?!!Object(arguments[1]).multiArgs:!1,r=O(t)(R(e,n));return r===S&&e._rejectCallback(r.e,!0),e._isFateSealed()||e._setAsyncGuaranteed(),e},i.all=function(t){return new E(t).promise()},i.cast=function(t){var e=j(t);return e instanceof i||(e=new i(b),e._captureStackTrace(),e._setFulfilled(),e._rejectionHandler0=t),e},i.resolve=i.fulfilled=i.cast,i.reject=i.rejected=function(t){var e=new i(b);return e._captureStackTrace(),e._rejectCallback(t,!0),e},i.setScheduler=function(t){if("function"!=typeof t)throw new m("expecting a function but got "+f.classString(t));return v.setScheduler(t)},i.prototype._then=function(t,e,n,r,o){var s=void 0!==o,a=s?o:new i(b),l=this._target(),u=l._bitField;s||(a._propagateFrom(this,3),a._captureStackTrace(),void 0===r&&0!==(2097152&this._bitField)&&(r=0!==(50397184&u)?this._boundValue():l===this?void 0:this._boundTo),this._fireEvent("promiseChained",this,a));var p=c();if(0!==(50397184&u)){var h,_,d=l._settlePromiseCtx;0!==(33554432&u)?(_=l._rejectionHandler0,h=t):0!==(16777216&u)?(_=l._fulfillmentHandler0,h=e,l._unsetRejectionIsUnhandled()):(d=l._settlePromiseLateCancellationObserver,_=new g("late cancellation observer"),l._attachExtraTrace(_),h=e),v.invoke(d,l,{handler:null===p?h:"function"==typeof h&&f.domainBind(p,h),promise:a,receiver:r,value:_})}else l._addCallbacks(t,e,a,r,p);return a},i.prototype._length=function(){return 65535&this._bitField},i.prototype._isFateSealed=function(){return 0!==(117506048&this._bitField)},i.prototype._isFollowing=function(){return 67108864===(67108864&this._bitField)},i.prototype._setLength=function(t){this._bitField=-65536&this._bitField|65535&t},i.prototype._setFulfilled=function(){this._bitField=33554432|this._bitField,this._fireEvent("promiseFulfilled",this)},i.prototype._setRejected=function(){this._bitField=16777216|this._bitField,this._fireEvent("promiseRejected",this)},i.prototype._setFollowing=function(){this._bitField=67108864|this._bitField,this._fireEvent("promiseResolved",this)},i.prototype._setIsFinal=function(){this._bitField=4194304|this._bitField},i.prototype._isFinal=function(){return(4194304&this._bitField)>0},i.prototype._unsetCancelled=function(){this._bitField=-65537&this._bitField},i.prototype._setCancelled=function(){this._bitField=65536|this._bitField,this._fireEvent("promiseCancelled",this)},i.prototype._setWillBeCancelled=function(){this._bitField=8388608|this._bitField},i.prototype._setAsyncGuaranteed=function(){v.hasCustomScheduler()||(this._bitField=134217728|this._bitField)},i.prototype._receiverAt=function(t){var e=0===t?this._receiver0:this[4*t-4+3];return e===h?void 0:void 0===e&&this._isBound()?this._boundValue():e},i.prototype._promiseAt=function(t){return this[4*t-4+2]},i.prototype._fulfillmentHandlerAt=function(t){return this[4*t-4+0]},i.prototype._rejectionHandlerAt=function(t){return this[4*t-4+1]},i.prototype._boundValue=function(){},i.prototype._migrateCallback0=function(t){var e=(t._bitField,t._fulfillmentHandler0),n=t._rejectionHandler0,r=t._promise0,i=t._receiverAt(0);void 0===i&&(i=h),this._addCallbacks(e,n,r,i,null)},i.prototype._migrateCallbackAt=function(t,e){var n=t._fulfillmentHandlerAt(e),r=t._rejectionHandlerAt(e),i=t._promiseAt(e),o=t._receiverAt(e);void 0===o&&(o=h),this._addCallbacks(n,r,i,o,null)},i.prototype._addCallbacks=function(t,e,n,r,i){var o=this._length();if(o>=65531&&(o=0,this._setLength(0)),0===o)this._promise0=n,this._receiver0=r,"function"==typeof t&&(this._fulfillmentHandler0=null===i?t:f.domainBind(i,t)),"function"==typeof e&&(this._rejectionHandler0=null===i?e:f.domainBind(i,e));else{var s=4*o-4;this[s+2]=n,this[s+3]=r,"function"==typeof t&&(this[s+0]=null===i?t:f.domainBind(i,t)),"function"==typeof e&&(this[s+1]=null===i?e:f.domainBind(i,e))}return this._setLength(o+1),o},i.prototype._proxy=function(t,e){this._addCallbacks(void 0,void 0,e,t,null)},i.prototype._resolveCallback=function(t,e){if(0===(117506048&this._bitField)){if(t===this)return this._rejectCallback(l(),!1);var n=j(t,this);if(!(n instanceof i))return this._fulfill(t);e&&this._propagateFrom(n,2);var r=n._target();if(r===this)return void this._reject(l());var o=r._bitField;if(0===(50397184&o)){var s=this._length();s>0&&r._migrateCallback0(this);for(var a=1;s>a;++a)r._migrateCallbackAt(this,a);this._setFollowing(),this._setLength(0),this._setFollowee(r)}else if(0!==(33554432&o))this._fulfill(r._value());else if(0!==(16777216&o))this._reject(r._reason());else{var c=new g("late cancellation observer");r._attachExtraTrace(c),this._reject(c)}}},i.prototype._rejectCallback=function(t,e,n){var r=f.ensureErrorObject(t),i=r===t;if(!i&&!n&&T.warnings()){var o="a promise was rejected with a non-error: "+f.classString(t);this._warn(o,!0)}this._attachExtraTrace(r,e?i:!1),this._reject(t)},i.prototype._resolveFromExecutor=function(t){if(t!==b){var e=this;this._captureStackTrace(),this._pushContext();var n=!0,r=this._execute(t,function(t){e._resolveCallback(t)},function(t){e._rejectCallback(t,n)});n=!1,this._popContext(),void 0!==r&&e._rejectCallback(r,!0)}},i.prototype._settlePromiseFromHandler=function(t,e,n,r){var i=r._bitField;if(0===(65536&i)){r._pushContext();var o;e===w?n&&"number"==typeof n.length?o=O(t).apply(this._boundValue(),n):(o=S,o.e=new m("cannot .spread() a non-array: "+f.classString(n))):o=O(t).call(e,n);var s=r._popContext();i=r._bitField,0===(65536&i)&&(o===C?r._reject(n):o===S?r._rejectCallback(o.e,!1):(T.checkForgottenReturns(o,s,"",r,this),r._resolveCallback(o)))}},i.prototype._target=function(){for(var t=this;t._isFollowing();)t=t._followee();return t},i.prototype._followee=function(){return this._rejectionHandler0},i.prototype._setFollowee=function(t){this._rejectionHandler0=t},i.prototype._settlePromise=function(t,e,r,o){var s=t instanceof i,a=this._bitField,c=0!==(134217728&a);0!==(65536&a)?(s&&t._invokeInternalOnCancel(),r instanceof x&&r.isFinallyHandler()?(r.cancelPromise=t,O(e).call(r,o)===S&&t._reject(S.e)):e===u?t._fulfill(u.call(r)):r instanceof n?r._promiseCancelled(t):s||t instanceof E?t._cancel():r.cancel()):"function"==typeof e?s?(c&&t._setAsyncGuaranteed(),this._settlePromiseFromHandler(e,r,o,t)):e.call(r,o,t):r instanceof n?r._isResolved()||(0!==(33554432&a)?r._promiseFulfilled(o,t):r._promiseRejected(o,t)):s&&(c&&t._setAsyncGuaranteed(),0!==(33554432&a)?t._fulfill(o):t._reject(o))},i.prototype._settlePromiseLateCancellationObserver=function(t){var e=t.handler,n=t.promise,r=t.receiver,o=t.value;"function"==typeof e?n instanceof i?this._settlePromiseFromHandler(e,r,o,n):e.call(r,o,n):n instanceof i&&n._reject(o)},i.prototype._settlePromiseCtx=function(t){this._settlePromise(t.promise,t.handler,t.receiver,t.value)},i.prototype._settlePromise0=function(t,e,n){var r=this._promise0,i=this._receiverAt(0);this._promise0=void 0,this._receiver0=void 0,this._settlePromise(r,t,i,e)},i.prototype._clearCallbackDataAtIndex=function(t){var e=4*t-4;this[e+2]=this[e+3]=this[e+0]=this[e+1]=void 0},i.prototype._fulfill=function(t){var e=this._bitField;if(!((117506048&e)>>>16)){if(t===this){var n=l();return this._attachExtraTrace(n),this._reject(n)}this._setFulfilled(),this._rejectionHandler0=t,(65535&e)>0&&(0!==(134217728&e)?this._settlePromises():v.settlePromises(this),this._dereferenceTrace())}},i.prototype._reject=function(t){var e=this._bitField;if(!((117506048&e)>>>16))return this._setRejected(),this._fulfillmentHandler0=t,this._isFinal()?v.fatalError(t,f.isNode):void((65535&e)>0?v.settlePromises(this):this._ensurePossibleRejectionHandled())},i.prototype._fulfillPromises=function(t,e){for(var n=1;t>n;n++){var r=this._fulfillmentHandlerAt(n),i=this._promiseAt(n),o=this._receiverAt(n);this._clearCallbackDataAtIndex(n),this._settlePromise(i,r,o,e)}},i.prototype._rejectPromises=function(t,e){for(var n=1;t>n;n++){var r=this._rejectionHandlerAt(n),i=this._promiseAt(n),o=this._receiverAt(n);this._clearCallbackDataAtIndex(n),this._settlePromise(i,r,o,e)}},i.prototype._settlePromises=function(){var t=this._bitField,e=65535&t;if(e>0){if(0!==(16842752&t)){var n=this._fulfillmentHandler0;this._settlePromise0(this._rejectionHandler0,n,t),this._rejectPromises(e,n)}else{var r=this._rejectionHandler0;this._settlePromise0(this._fulfillmentHandler0,r,t),this._fulfillPromises(e,r)}this._setLength(0)}this._clearCancellationData()},i.prototype._settledValue=function(){var t=this._bitField;return 0!==(33554432&t)?this._rejectionHandler0:0!==(16777216&t)?this._fulfillmentHandler0:void 0},i.defer=i.pending=function(){T.deprecated("Promise.defer","new Promise");var t=new i(b);return{promise:t,resolve:o,reject:s}},f.notEnumerableProp(i,"_makeSelfResolutionError",l),t("./method")(i,b,j,p,T),t("./bind")(i,b,j,T),t("./cancel")(i,E,p,T),t("./direct_resolve")(i),t("./synchronous_inspection")(i),t("./join")(i,E,j,b,v,c),i.Promise=i,i.version="3.5.3",t("./map.js")(i,E,p,j,b,T),t("./call_get.js")(i),t("./using.js")(i,p,j,F,b,T),t("./timers.js")(i,b,T),t("./generators.js")(i,p,b,j,n,T),t("./nodeify.js")(i),t("./promisify.js")(i,b),t("./props.js")(i,E,j,p),t("./race.js")(i,b,j,p),t("./reduce.js")(i,E,p,j,b,T),t("./settle.js")(i,E,T),t("./some.js")(i,E,p),t("./filter.js")(i,b),t("./each.js")(i,b),t("./any.js")(i),f.toFastProperties(i),f.toFastProperties(i.prototype),a({a:1}),a({b:2}),a({c:3}),a(1),a(function(){}),a(void 0),a(!1),a(new i(b)),T.setBounds(d.firstLineError,f.lastLineError),i}},{"./any.js":1,"./async":2,"./bind":3,"./call_get.js":5,"./cancel":6,"./catch_filter":7,"./context":8,"./debuggability":9,"./direct_resolve":10,"./each.js":11,"./errors":12,"./es5":13,"./filter.js":14,"./finally":15,"./generators.js":16,"./join":17,"./map.js":18,"./method":19,"./nodeback":20,"./nodeify.js":21,"./promise_array":23,"./promisify.js":24,"./props.js":25,"./race.js":27,"./reduce.js":28,"./settle.js":30,"./some.js":31,"./synchronous_inspection":32,"./thenables":33,"./timers.js":34,"./using.js":35,"./util":36}],23:[function(t,e,n){"use strict";e.exports=function(e,n,r,i,o){function s(t){switch(t){case-2:return[];case-3:return{};case-6:return new Map}}function a(t){var r=this._promise=new e(n);t instanceof e&&r._propagateFrom(t,3),r._setOnCancel(this),this._values=t,this._length=0,this._totalResolved=0,this._init(void 0,-2)}var c=t("./util");c.isArray;return c.inherits(a,o),a.prototype.length=function(){return this._length},a.prototype.promise=function(){return this._promise},a.prototype._init=function l(t,n){var o=r(this._values,this._promise);if(o instanceof e){o=o._target();var a=o._bitField;if(this._values=o,0===(50397184&a))return this._promise._setAsyncGuaranteed(),o._then(l,this._reject,void 0,this,n);if(0===(33554432&a))return 0!==(16777216&a)?this._reject(o._reason()):this._cancel();o=o._value()}if(o=c.asArray(o),null===o){var u=i("expecting an array or an iterable object but got "+c.classString(o)).reason();return void this._promise._rejectCallback(u,!1)}return 0===o.length?void(-5===n?this._resolveEmptyArray():this._resolve(s(n))):void this._iterate(o)},a.prototype._iterate=function(t){var n=this.getActualLength(t.length);this._length=n,this._values=this.shouldCopyValues()?new Array(n):this._values;for(var i=this._promise,o=!1,s=null,a=0;n>a;++a){var c=r(t[a],i);c instanceof e?(c=c._target(),s=c._bitField):s=null,o?null!==s&&c.suppressUnhandledRejections():null!==s?0===(50397184&s)?(c._proxy(this,a),this._values[a]=c):o=0!==(33554432&s)?this._promiseFulfilled(c._value(),a):0!==(16777216&s)?this._promiseRejected(c._reason(),a):this._promiseCancelled(a):o=this._promiseFulfilled(c,a)}o||i._setAsyncGuaranteed()},a.prototype._isResolved=function(){return null===this._values},a.prototype._resolve=function(t){this._values=null,this._promise._fulfill(t)},a.prototype._cancel=function(){!this._isResolved()&&this._promise._isCancellable()&&(this._values=null,this._promise._cancel())},a.prototype._reject=function(t){this._values=null,this._promise._rejectCallback(t,!1)},a.prototype._promiseFulfilled=function(t,e){this._values[e]=t;var n=++this._totalResolved;return n>=this._length?(this._resolve(this._values),!0):!1},a.prototype._promiseCancelled=function(){return this._cancel(),!0},a.prototype._promiseRejected=function(t){return this._totalResolved++,this._reject(t),!0},a.prototype._resultCancelled=function(){if(!this._isResolved()){var t=this._values;if(this._cancel(),t instanceof e)t.cancel();else for(var n=0;nc;c+=2){var u=s[c],p=s[c+1],_=u+e;if(r===k)t[_]=k(u,h,u,p,e,i);else{var d=r(p,function(){return k(u,h,u,p,e,i)});f.notEnumerableProp(d,"__isPromisified__",!0),t[_]=d}}return f.toFastProperties(t),t}function u(t,e,n){return k(t,e,void 0,t,null,n)}var p,h={},f=t("./util"),_=t("./nodeback"),d=f.withAppended,v=f.maybeWrapAsError,y=f.canEvaluate,m=t("./errors").TypeError,g="Async",b={__isPromisified__:!0},w=["arity","length","name","arguments","caller","callee","prototype","__isPromisified__"],C=new RegExp("^(?:"+w.join("|")+")$"),j=function(t){return f.isIdentifier(t)&&"_"!==t.charAt(0)&&"constructor"!==t},E=function(t){return t.replace(/([$])/,"\\$")},k=y?p:c;e.promisify=function(t,e){if("function"!=typeof t)throw new m("expecting a function but got "+f.classString(t));if(i(t))return t;e=Object(e);var n=void 0===e.context?h:e.context,o=!!e.multiArgs,s=u(t,n,o);return f.copyDescriptors(t,s,r),s},e.promisifyAll=function(t,e){if("function"!=typeof t&&"object"!=typeof t)throw new m("the target of promisifyAll must be an object or a function\n\n See http://goo.gl/MqrFmX\n");e=Object(e);var n=!!e.multiArgs,r=e.suffix;"string"!=typeof r&&(r=g);var i=e.filter;"function"!=typeof i&&(i=j);var o=e.promisifier;if("function"!=typeof o&&(o=k),!f.isIdentifier(r))throw new RangeError("suffix must be a valid identifier\n\n See http://goo.gl/MqrFmX\n");for(var s=f.inheritedDataKeys(t),a=0;ao;++o){var s=r[o];e[o]=t[s],e[o+i]=s}}this.constructor$(e),this._isMap=n,this._init$(void 0,n?-6:-3)}function s(t){var n,s=r(t);return l(s)?(n=s instanceof e?s._then(e.props,void 0,void 0,void 0,void 0):new o(s).promise(),s instanceof e&&n._propagateFrom(s,2),n):i("cannot await properties of a non-object\n\n See http://goo.gl/MqrFmX\n")}var a,c=t("./util"),l=c.isObject,u=t("./es5");"function"==typeof Map&&(a=Map);var p=function(){function t(t,r){this[e]=t,this[e+n]=r,e++}var e=0,n=0;return function(r){n=r.size,e=0;var i=new Array(2*r.size);return r.forEach(t,i),i}}(),h=function(t){for(var e=new a,n=t.length/2|0,r=0;n>r;++r){var i=t[n+r],o=t[r];e.set(i,o)}return e};c.inherits(o,n),o.prototype._init=function(){},o.prototype._promiseFulfilled=function(t,e){this._values[e]=t;var n=++this._totalResolved;if(n>=this._length){var r;if(this._isMap)r=h(this._values);else{r={};for(var i=this.length(),o=0,s=this.length();s>o;++o)r[this._values[o+i]]=this._values[o]}return this._resolve(r),!0}return!1},o.prototype.shouldCopyValues=function(){return!1},o.prototype.getActualLength=function(t){return t>>1},e.prototype.props=function(){return s(this)},e.props=function(t){return s(t)}}},{"./es5":13,"./util":36}],26:[function(t,e,n){"use strict";function r(t,e,n,r,i){for(var o=0;i>o;++o)n[o+r]=t[o+e],t[o+e]=void 0}function i(t){this._capacity=t,this._length=0,this._front=0}i.prototype._willBeOverCapacity=function(t){return this._capacityh;++h){var _=t[h];(void 0!==_||h in t)&&e.cast(_)._then(u,p,void 0,l,null)}return l}var s=t("./util"),a=function(t){return t.then(function(e){return o(e,t)})};e.race=function(t){return o(t,void 0)},e.prototype.race=function(){return o(this,void 0)}}},{"./util":36}],28:[function(t,e,n){"use strict";e.exports=function(e,n,r,i,o,s){function a(t,n,r,i){this.constructor$(t);var s=h();this._fn=null===s?n:f.domainBind(s,n),void 0!==r&&(r=e.resolve(r),r._attachCancellationCallback(this)),this._initialValue=r,this._currentCancellable=null,i===o?this._eachValues=Array(this._length):0===i?this._eachValues=null:this._eachValues=void 0,this._promise._captureStackTrace(),this._init$(void 0,-5)}function c(t,e){this.isFulfilled()?e._resolve(t):e._reject(t)}function l(t,e,n,i){if("function"!=typeof e)return r("expecting a function but got "+f.classString(e));var o=new a(t,e,n,i);return o.promise()}function u(t){this.accum=t,this.array._gotAccum(t);var n=i(this.value,this.array._promise);return n instanceof e?(this.array._currentCancellable=n,n._then(p,void 0,void 0,this,void 0)):p.call(this,n)}function p(t){var n=this.array,r=n._promise,i=_(n._fn);r._pushContext();var o;o=void 0!==n._eachValues?i.call(r._boundValue(),t,this.index,this.length):i.call(r._boundValue(),this.accum,t,this.index,this.length),o instanceof e&&(n._currentCancellable=o);var a=r._popContext();return s.checkForgottenReturns(o,a,void 0!==n._eachValues?"Promise.each":"Promise.reduce",r),o}var h=e._getDomain,f=t("./util"),_=f.tryCatch;f.inherits(a,n),a.prototype._gotAccum=function(t){void 0!==this._eachValues&&null!==this._eachValues&&t!==o&&this._eachValues.push(t)},a.prototype._eachComplete=function(t){return null!==this._eachValues&&this._eachValues.push(t),this._eachValues},a.prototype._init=function(){},a.prototype._resolveEmptyArray=function(){this._resolve(void 0!==this._eachValues?this._eachValues:this._initialValue)},a.prototype.shouldCopyValues=function(){return!1},a.prototype._resolve=function(t){this._promise._resolveCallback(t),this._values=null},a.prototype._resultCancelled=function(t){return t===this._initialValue?this._cancel():void(this._isResolved()||(this._resultCancelled$(),this._currentCancellable instanceof e&&this._currentCancellable.cancel(),this._initialValue instanceof e&&this._initialValue.cancel()))},a.prototype._iterate=function(t){this._values=t;var n,r,i=t.length;if(void 0!==this._initialValue?(n=this._initialValue,r=0):(n=e.resolve(t[0]),r=1),this._currentCancellable=n,!n.isRejected())for(;i>r;++r){var o={accum:null,value:t[r],index:r,length:i,array:this};n=n._then(u,void 0,void 0,o,void 0)}void 0!==this._eachValues&&(n=n._then(this._eachComplete,void 0,void 0,this,void 0)),n._then(c,c,void 0,n,this)},e.prototype.reduce=function(t,e){return l(this,t,e,null)},e.reduce=function(t,e,n,r){return l(t,e,n,r)}}},{"./util":36}],29:[function(t,e,n){"use strict";var r,i=t("./util"),o=function(){throw new Error("No async scheduler available\n\n See http://goo.gl/MqrFmX\n")},s=i.getNativePromise();if(i.isNode&&"undefined"==typeof MutationObserver){var a=global.setImmediate,c=process.nextTick;r=i.isRecentNode?function(t){a.call(global,t)}:function(t){c.call(process,t)}}else if("function"==typeof s&&"function"==typeof s.resolve){var l=s.resolve();r=function(t){l.then(t)}}else r="undefined"==typeof MutationObserver||"undefined"!=typeof window&&window.navigator&&(window.navigator.standalone||window.cordova)?"undefined"!=typeof setImmediate?function(t){setImmediate(t)}:"undefined"!=typeof setTimeout?function(t){setTimeout(t,0)}:o:function(){var t=document.createElement("div"),e={attributes:!0},n=!1,r=document.createElement("div"),i=new MutationObserver(function(){t.classList.toggle("foo"),n=!1});i.observe(r,e);var o=function(){n||(n=!0,r.classList.toggle("foo"))};return function(n){var r=new MutationObserver(function(){r.disconnect(),n()});r.observe(t,e),o()}}();e.exports=r},{"./util":36}],30:[function(t,e,n){"use strict";e.exports=function(e,n,r){function i(t){this.constructor$(t)}var o=e.PromiseInspection,s=t("./util");s.inherits(i,n),i.prototype._promiseResolved=function(t,e){this._values[t]=e;var n=++this._totalResolved;return n>=this._length?(this._resolve(this._values),!0):!1},i.prototype._promiseFulfilled=function(t,e){var n=new o;return n._bitField=33554432,n._settledValueField=t,this._promiseResolved(e,n)},i.prototype._promiseRejected=function(t,e){var n=new o;return n._bitField=16777216, +n._settledValueField=t,this._promiseResolved(e,n)},e.settle=function(t){return r.deprecated(".settle()",".reflect()"),new i(t).promise()},e.prototype.settle=function(){return e.settle(this)}}},{"./util":36}],31:[function(t,e,n){"use strict";e.exports=function(e,n,r){function i(t){this.constructor$(t),this._howMany=0,this._unwrap=!1,this._initialized=!1}function o(t,e){if((0|e)!==e||0>e)return r("expecting a positive integer\n\n See http://goo.gl/MqrFmX\n");var n=new i(t),o=n.promise();return n.setHowMany(e),n.init(),o}var s=t("./util"),a=t("./errors").RangeError,c=t("./errors").AggregateError,l=s.isArray,u={};s.inherits(i,n),i.prototype._init=function(){if(this._initialized){if(0===this._howMany)return void this._resolve([]);this._init$(void 0,-5);var t=l(this._values);!this._isResolved()&&t&&this._howMany>this._canPossiblyFulfill()&&this._reject(this._getRangeError(this.length()))}},i.prototype.init=function(){this._initialized=!0,this._init()},i.prototype.setUnwrap=function(){this._unwrap=!0},i.prototype.howMany=function(){return this._howMany},i.prototype.setHowMany=function(t){this._howMany=t},i.prototype._promiseFulfilled=function(t){return this._addFulfilled(t),this._fulfilled()===this.howMany()?(this._values.length=this.howMany(),1===this.howMany()&&this._unwrap?this._resolve(this._values[0]):this._resolve(this._values),!0):!1},i.prototype._promiseRejected=function(t){return this._addRejected(t),this._checkOutcome()},i.prototype._promiseCancelled=function(){return this._values instanceof e||null==this._values?this._cancel():(this._addRejected(u),this._checkOutcome())},i.prototype._checkOutcome=function(){if(this.howMany()>this._canPossiblyFulfill()){for(var t=new c,e=this.length();e0?this._reject(t):this._cancel(),!0}return!1},i.prototype._fulfilled=function(){return this._totalResolved},i.prototype._rejected=function(){return this._values.length-this.length()},i.prototype._addRejected=function(t){this._values.push(t)},i.prototype._addFulfilled=function(t){this._values[this._totalResolved++]=t},i.prototype._canPossiblyFulfill=function(){return this.length()-this._rejected()},i.prototype._getRangeError=function(t){var e="Input array must contain at least "+this._howMany+" items but contains only "+t+" items";return new a(e)},i.prototype._resolveEmptyArray=function(){this._reject(this._getRangeError(0))},e.some=function(t,e){return o(t,e)},e.prototype.some=function(t){return o(this,t)},e._SomePromiseArray=i}},{"./errors":12,"./util":36}],32:[function(t,e,n){"use strict";e.exports=function(t){function e(t){void 0!==t?(t=t._target(),this._bitField=t._bitField,this._settledValueField=t._isFateSealed()?t._settledValue():void 0):(this._bitField=0,this._settledValueField=void 0)}e.prototype._settledValue=function(){return this._settledValueField};var n=e.prototype.value=function(){if(!this.isFulfilled())throw new TypeError("cannot get fulfillment value of a non-fulfilled promise\n\n See http://goo.gl/MqrFmX\n");return this._settledValue()},r=e.prototype.error=e.prototype.reason=function(){if(!this.isRejected())throw new TypeError("cannot get rejection reason of a non-rejected promise\n\n See http://goo.gl/MqrFmX\n");return this._settledValue()},i=e.prototype.isFulfilled=function(){return 0!==(33554432&this._bitField)},o=e.prototype.isRejected=function(){return 0!==(16777216&this._bitField)},s=e.prototype.isPending=function(){return 0===(50397184&this._bitField)},a=e.prototype.isResolved=function(){return 0!==(50331648&this._bitField)};e.prototype.isCancelled=function(){return 0!==(8454144&this._bitField)},t.prototype.__isCancelled=function(){return 65536===(65536&this._bitField)},t.prototype._isCancelled=function(){return this._target().__isCancelled()},t.prototype.isCancelled=function(){return 0!==(8454144&this._target()._bitField)},t.prototype.isPending=function(){return s.call(this._target())},t.prototype.isRejected=function(){return o.call(this._target())},t.prototype.isFulfilled=function(){return i.call(this._target())},t.prototype.isResolved=function(){return a.call(this._target())},t.prototype.value=function(){return n.call(this._target())},t.prototype.reason=function(){var t=this._target();return t._unsetRejectionIsUnhandled(),r.call(t)},t.prototype._value=function(){return this._settledValue()},t.prototype._reason=function(){return this._unsetRejectionIsUnhandled(),this._settledValue()},t.PromiseInspection=e}},{}],33:[function(t,e,n){"use strict";e.exports=function(e,n){function r(t,r){if(u(t)){if(t instanceof e)return t;var i=o(t);if(i===l){r&&r._pushContext();var c=e.reject(i.e);return r&&r._popContext(),c}if("function"==typeof i){if(s(t)){var c=new e(n);return t._then(c._fulfill,c._reject,void 0,c,null),c}return a(t,i,r)}}return t}function i(t){return t.then}function o(t){try{return i(t)}catch(e){return l.e=e,l}}function s(t){try{return p.call(t,"_promise0")}catch(e){return!1}}function a(t,r,i){function o(t){a&&(a._resolveCallback(t),a=null)}function s(t){a&&(a._rejectCallback(t,p,!0),a=null)}var a=new e(n),u=a;i&&i._pushContext(),a._captureStackTrace(),i&&i._popContext();var p=!0,h=c.tryCatch(r).call(t,o,s);return p=!1,a&&h===l&&(a._rejectCallback(h.e,!0,!0),a=null),u}var c=t("./util"),l=c.errorObj,u=c.isObject,p={}.hasOwnProperty;return r}},{"./util":36}],34:[function(t,e,n){"use strict";e.exports=function(e,n,r){function i(t){this.handle=t}function o(t){return clearTimeout(this.handle),t}function s(t){throw clearTimeout(this.handle),t}var a=t("./util"),c=e.TimeoutError;i.prototype._resultCancelled=function(){clearTimeout(this.handle)};var l=function(t){return u(+this).thenReturn(t)},u=e.delay=function(t,o){var s,a;return void 0!==o?(s=e.resolve(o)._then(l,null,null,t,void 0),r.cancellation()&&o instanceof e&&s._setOnCancel(o)):(s=new e(n),a=setTimeout(function(){s._fulfill()},+t),r.cancellation()&&s._setOnCancel(new i(a)),s._captureStackTrace()),s._setAsyncGuaranteed(),s};e.prototype.delay=function(t){return u(t,this)};var p=function(t,e,n){var r;r="string"!=typeof e?e instanceof Error?e:new c("operation timed out"):new c(e),a.markAsOriginatingFromRejection(r),t._attachExtraTrace(r),t._reject(r),null!=n&&n.cancel()};e.prototype.timeout=function(t,e){t=+t;var n,a,c=new i(setTimeout(function(){n.isPending()&&p(n,e,a)},t));return r.cancellation()?(a=this.then(),n=a._then(o,s,void 0,c,void 0),n._setOnCancel(c)):n=this._then(o,s,void 0,c,void 0),n}}},{"./util":36}],35:[function(t,e,n){"use strict";e.exports=function(e,n,r,i,o,s){function a(t){setTimeout(function(){throw t},0)}function c(t){var e=r(t);return e!==t&&"function"==typeof t._isDisposable&&"function"==typeof t._getDisposer&&t._isDisposable()&&e._setDisposable(t._getDisposer()),e}function l(t,n){function i(){if(s>=l)return u._fulfill();var o=c(t[s++]);if(o instanceof e&&o._isDisposable()){try{o=r(o._getDisposer().tryDispose(n),t.promise)}catch(p){return a(p)}if(o instanceof e)return o._then(i,a,null,null,null)}i()}var s=0,l=t.length,u=new e(o);return i(),u}function u(t,e,n){this._data=t,this._promise=e,this._context=n}function p(t,e,n){this.constructor$(t,e,n)}function h(t){return u.isDisposer(t)?(this.resources[this.index]._setDisposable(t),t.promise()):t}function f(t){this.length=t,this.promise=null,this[t-1]=null}var _=t("./util"),d=t("./errors").TypeError,v=t("./util").inherits,y=_.errorObj,m=_.tryCatch,g={};u.prototype.data=function(){return this._data},u.prototype.promise=function(){return this._promise},u.prototype.resource=function(){return this.promise().isFulfilled()?this.promise().value():g},u.prototype.tryDispose=function(t){var e=this.resource(),n=this._context;void 0!==n&&n._pushContext();var r=e!==g?this.doDispose(e,t):null;return void 0!==n&&n._popContext(),this._promise._unsetDisposable(),this._data=null,r},u.isDisposer=function(t){return null!=t&&"function"==typeof t.resource&&"function"==typeof t.tryDispose},v(p,u),p.prototype.doDispose=function(t,e){var n=this.data();return n.call(t,t,e)},f.prototype._resultCancelled=function(){for(var t=this.length,n=0;t>n;++n){var r=this[n];r instanceof e&&r.cancel()}},e.using=function(){var t=arguments.length;if(2>t)return n("you must pass at least 2 arguments to Promise.using");var i=arguments[t-1];if("function"!=typeof i)return n("expecting a function but got "+_.classString(i));var o,a=!0;2===t&&Array.isArray(arguments[0])?(o=arguments[0],t=o.length,a=!1):(o=arguments,t--);for(var c=new f(t),p=0;t>p;++p){var d=o[p];if(u.isDisposer(d)){var v=d;d=d.promise(),d._setDisposable(v)}else{var g=r(d);g instanceof e&&(d=g._then(h,null,null,{resources:c,index:p},void 0))}c[p]=d}for(var b=new Array(c.length),p=0;p0},e.prototype._getDisposer=function(){return this._disposer},e.prototype._unsetDisposable=function(){this._bitField=-131073&this._bitField,this._disposer=void 0},e.prototype.disposer=function(t){if("function"==typeof t)return new p(t,this,i());throw new d}}},{"./errors":12,"./util":36}],36:[function(t,e,n){"use strict";function r(){try{var t=P;return P=null,t.apply(this,arguments)}catch(e){return x.e=e,x}}function i(t){return P=t,r}function o(t){return null==t||t===!0||t===!1||"string"==typeof t||"number"==typeof t}function s(t){return"function"==typeof t||"object"==typeof t&&null!==t}function a(t){return o(t)?new Error(v(t)):t}function c(t,e){var n,r=t.length,i=new Array(r+1);for(n=0;r>n;++n)i[n]=t[n];return i[n]=e,i}function l(t,e,n){if(!F.isES5)return{}.hasOwnProperty.call(t,e)?t[e]:void 0;var r=Object.getOwnPropertyDescriptor(t,e);return null!=r?null==r.get&&null==r.set?r.value:n:void 0}function u(t,e,n){if(o(t))return t;var r={value:n,configurable:!0,enumerable:!1,writable:!0};return F.defineProperty(t,e,r),t}function p(t){throw t}function h(t){try{if("function"==typeof t){var e=F.names(t.prototype),n=F.isES5&&e.length>1,r=e.length>0&&!(1===e.length&&"constructor"===e[0]),i=A.test(t+"")&&F.names(t).length>0;if(n||r||i)return!0}return!1}catch(o){return!1}}function f(t){function e(){}function n(){return typeof r.foo}e.prototype=t;var r=new e;return n(),n(),t}function _(t){return D.test(t)}function d(t,e,n){for(var r=new Array(t),i=0;t>i;++i)r[i]=e+i+n;return r}function v(t){try{return t+""}catch(e){return"[no string representation]"}}function y(t){return t instanceof Error||null!==t&&"object"==typeof t&&"string"==typeof t.message&&"string"==typeof t.name}function m(t){try{u(t,"isOperational",!0)}catch(e){}}function g(t){return null==t?!1:t instanceof Error.__BluebirdErrorTypes__.OperationalError||t.isOperational===!0}function b(t){return y(t)&&F.propertyIsWritable(t,"stack")}function w(t){return{}.toString.call(t)}function C(t,e,n){for(var r=F.names(t),i=0;i10||t[0]>0}(),B.isNode&&B.toFastProperties(process);try{throw new Error}catch(U){B.lastLineError=U}e.exports=B},{"./es5":13}]},{},[4])(4)}),"undefined"!=typeof window&&null!==window?window.P=window.Promise:"undefined"!=typeof self&&null!==self&&(self.P=self.Promise); \ No newline at end of file diff --git a/express-server/node_modules/bluebird/js/release/any.js b/express-server/node_modules/bluebird/js/release/any.js new file mode 100644 index 00000000..05a6228e --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/any.js @@ -0,0 +1,21 @@ +"use strict"; +module.exports = function(Promise) { +var SomePromiseArray = Promise._SomePromiseArray; +function any(promises) { + var ret = new SomePromiseArray(promises); + var promise = ret.promise(); + ret.setHowMany(1); + ret.setUnwrap(); + ret.init(); + return promise; +} + +Promise.any = function (promises) { + return any(promises); +}; + +Promise.prototype.any = function () { + return any(this); +}; + +}; diff --git a/express-server/node_modules/bluebird/js/release/assert.js b/express-server/node_modules/bluebird/js/release/assert.js new file mode 100644 index 00000000..4518231a --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/assert.js @@ -0,0 +1,55 @@ +"use strict"; +module.exports = (function(){ +var AssertionError = (function() { + function AssertionError(a) { + this.constructor$(a); + this.message = a; + this.name = "AssertionError"; + } + AssertionError.prototype = new Error(); + AssertionError.prototype.constructor = AssertionError; + AssertionError.prototype.constructor$ = Error; + return AssertionError; +})(); + +function getParams(args) { + var params = []; + for (var i = 0; i < args.length; ++i) params.push("arg" + i); + return params; +} + +function nativeAssert(callName, args, expect) { + try { + var params = getParams(args); + var constructorArgs = params; + constructorArgs.push("return " + + callName + "("+ params.join(",") + ");"); + var fn = Function.apply(null, constructorArgs); + return fn.apply(null, args); + } catch (e) { + if (!(e instanceof SyntaxError)) { + throw e; + } else { + return expect; + } + } +} + +return function assert(boolExpr, message) { + if (boolExpr === true) return; + + if (typeof boolExpr === "string" && + boolExpr.charAt(0) === "%") { + var nativeCallName = boolExpr; + var $_len = arguments.length;var args = new Array(Math.max($_len - 2, 0)); for(var $_i = 2; $_i < $_len; ++$_i) {args[$_i - 2] = arguments[$_i];}; + if (nativeAssert(nativeCallName, args, message) === message) return; + message = (nativeCallName + " !== " + message); + } + + var ret = new AssertionError(message); + if (Error.captureStackTrace) { + Error.captureStackTrace(ret, assert); + } + throw ret; +}; +})(); diff --git a/express-server/node_modules/bluebird/js/release/async.js b/express-server/node_modules/bluebird/js/release/async.js new file mode 100644 index 00000000..73cdc611 --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/async.js @@ -0,0 +1,165 @@ +"use strict"; +var firstLineError; +try {throw new Error(); } catch (e) {firstLineError = e;} +var schedule = require("./schedule"); +var Queue = require("./queue"); +var util = require("./util"); + +function Async() { + this._customScheduler = false; + this._isTickUsed = false; + this._lateQueue = new Queue(16); + this._normalQueue = new Queue(16); + this._haveDrainedQueues = false; + this._trampolineEnabled = true; + var self = this; + this.drainQueues = function () { + self._drainQueues(); + }; + this._schedule = schedule; +} + +Async.prototype.setScheduler = function(fn) { + var prev = this._schedule; + this._schedule = fn; + this._customScheduler = true; + return prev; +}; + +Async.prototype.hasCustomScheduler = function() { + return this._customScheduler; +}; + +Async.prototype.enableTrampoline = function() { + this._trampolineEnabled = true; +}; + +Async.prototype.disableTrampolineIfNecessary = function() { + if (util.hasDevTools) { + this._trampolineEnabled = false; + } +}; + +Async.prototype.haveItemsQueued = function () { + return this._isTickUsed || this._haveDrainedQueues; +}; + + +Async.prototype.fatalError = function(e, isNode) { + if (isNode) { + process.stderr.write("Fatal " + (e instanceof Error ? e.stack : e) + + "\n"); + process.exit(2); + } else { + this.throwLater(e); + } +}; + +Async.prototype.throwLater = function(fn, arg) { + if (arguments.length === 1) { + arg = fn; + fn = function () { throw arg; }; + } + if (typeof setTimeout !== "undefined") { + setTimeout(function() { + fn(arg); + }, 0); + } else try { + this._schedule(function() { + fn(arg); + }); + } catch (e) { + throw new Error("No async scheduler available\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } +}; + +function AsyncInvokeLater(fn, receiver, arg) { + this._lateQueue.push(fn, receiver, arg); + this._queueTick(); +} + +function AsyncInvoke(fn, receiver, arg) { + this._normalQueue.push(fn, receiver, arg); + this._queueTick(); +} + +function AsyncSettlePromises(promise) { + this._normalQueue._pushOne(promise); + this._queueTick(); +} + +if (!util.hasDevTools) { + Async.prototype.invokeLater = AsyncInvokeLater; + Async.prototype.invoke = AsyncInvoke; + Async.prototype.settlePromises = AsyncSettlePromises; +} else { + Async.prototype.invokeLater = function (fn, receiver, arg) { + if (this._trampolineEnabled) { + AsyncInvokeLater.call(this, fn, receiver, arg); + } else { + this._schedule(function() { + setTimeout(function() { + fn.call(receiver, arg); + }, 100); + }); + } + }; + + Async.prototype.invoke = function (fn, receiver, arg) { + if (this._trampolineEnabled) { + AsyncInvoke.call(this, fn, receiver, arg); + } else { + this._schedule(function() { + fn.call(receiver, arg); + }); + } + }; + + Async.prototype.settlePromises = function(promise) { + if (this._trampolineEnabled) { + AsyncSettlePromises.call(this, promise); + } else { + this._schedule(function() { + promise._settlePromises(); + }); + } + }; +} + +function _drainQueue(queue) { + while (queue.length() > 0) { + _drainQueueStep(queue); + } +} + +function _drainQueueStep(queue) { + var fn = queue.shift(); + if (typeof fn !== "function") { + fn._settlePromises(); + } else { + var receiver = queue.shift(); + var arg = queue.shift(); + fn.call(receiver, arg); + } +} + +Async.prototype._drainQueues = function () { + _drainQueue(this._normalQueue); + this._reset(); + this._haveDrainedQueues = true; + _drainQueue(this._lateQueue); +}; + +Async.prototype._queueTick = function () { + if (!this._isTickUsed) { + this._isTickUsed = true; + this._schedule(this.drainQueues); + } +}; + +Async.prototype._reset = function () { + this._isTickUsed = false; +}; + +module.exports = Async; +module.exports.firstLineError = firstLineError; diff --git a/express-server/node_modules/bluebird/js/release/bind.js b/express-server/node_modules/bluebird/js/release/bind.js new file mode 100644 index 00000000..fc3379db --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/bind.js @@ -0,0 +1,67 @@ +"use strict"; +module.exports = function(Promise, INTERNAL, tryConvertToPromise, debug) { +var calledBind = false; +var rejectThis = function(_, e) { + this._reject(e); +}; + +var targetRejected = function(e, context) { + context.promiseRejectionQueued = true; + context.bindingPromise._then(rejectThis, rejectThis, null, this, e); +}; + +var bindingResolved = function(thisArg, context) { + if (((this._bitField & 50397184) === 0)) { + this._resolveCallback(context.target); + } +}; + +var bindingRejected = function(e, context) { + if (!context.promiseRejectionQueued) this._reject(e); +}; + +Promise.prototype.bind = function (thisArg) { + if (!calledBind) { + calledBind = true; + Promise.prototype._propagateFrom = debug.propagateFromFunction(); + Promise.prototype._boundValue = debug.boundValueFunction(); + } + var maybePromise = tryConvertToPromise(thisArg); + var ret = new Promise(INTERNAL); + ret._propagateFrom(this, 1); + var target = this._target(); + ret._setBoundTo(maybePromise); + if (maybePromise instanceof Promise) { + var context = { + promiseRejectionQueued: false, + promise: ret, + target: target, + bindingPromise: maybePromise + }; + target._then(INTERNAL, targetRejected, undefined, ret, context); + maybePromise._then( + bindingResolved, bindingRejected, undefined, ret, context); + ret._setOnCancel(maybePromise); + } else { + ret._resolveCallback(target); + } + return ret; +}; + +Promise.prototype._setBoundTo = function (obj) { + if (obj !== undefined) { + this._bitField = this._bitField | 2097152; + this._boundTo = obj; + } else { + this._bitField = this._bitField & (~2097152); + } +}; + +Promise.prototype._isBound = function () { + return (this._bitField & 2097152) === 2097152; +}; + +Promise.bind = function (thisArg, value) { + return Promise.resolve(value).bind(thisArg); +}; +}; diff --git a/express-server/node_modules/bluebird/js/release/bluebird.js b/express-server/node_modules/bluebird/js/release/bluebird.js new file mode 100644 index 00000000..1c36cf36 --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/bluebird.js @@ -0,0 +1,11 @@ +"use strict"; +var old; +if (typeof Promise !== "undefined") old = Promise; +function noConflict() { + try { if (Promise === bluebird) Promise = old; } + catch (e) {} + return bluebird; +} +var bluebird = require("./promise")(); +bluebird.noConflict = noConflict; +module.exports = bluebird; diff --git a/express-server/node_modules/bluebird/js/release/call_get.js b/express-server/node_modules/bluebird/js/release/call_get.js new file mode 100644 index 00000000..0ed7714a --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/call_get.js @@ -0,0 +1,123 @@ +"use strict"; +var cr = Object.create; +if (cr) { + var callerCache = cr(null); + var getterCache = cr(null); + callerCache[" size"] = getterCache[" size"] = 0; +} + +module.exports = function(Promise) { +var util = require("./util"); +var canEvaluate = util.canEvaluate; +var isIdentifier = util.isIdentifier; + +var getMethodCaller; +var getGetter; +if (!false) { +var makeMethodCaller = function (methodName) { + return new Function("ensureMethod", " \n\ + return function(obj) { \n\ + 'use strict' \n\ + var len = this.length; \n\ + ensureMethod(obj, 'methodName'); \n\ + switch(len) { \n\ + case 1: return obj.methodName(this[0]); \n\ + case 2: return obj.methodName(this[0], this[1]); \n\ + case 3: return obj.methodName(this[0], this[1], this[2]); \n\ + case 0: return obj.methodName(); \n\ + default: \n\ + return obj.methodName.apply(obj, this); \n\ + } \n\ + }; \n\ + ".replace(/methodName/g, methodName))(ensureMethod); +}; + +var makeGetter = function (propertyName) { + return new Function("obj", " \n\ + 'use strict'; \n\ + return obj.propertyName; \n\ + ".replace("propertyName", propertyName)); +}; + +var getCompiled = function(name, compiler, cache) { + var ret = cache[name]; + if (typeof ret !== "function") { + if (!isIdentifier(name)) { + return null; + } + ret = compiler(name); + cache[name] = ret; + cache[" size"]++; + if (cache[" size"] > 512) { + var keys = Object.keys(cache); + for (var i = 0; i < 256; ++i) delete cache[keys[i]]; + cache[" size"] = keys.length - 256; + } + } + return ret; +}; + +getMethodCaller = function(name) { + return getCompiled(name, makeMethodCaller, callerCache); +}; + +getGetter = function(name) { + return getCompiled(name, makeGetter, getterCache); +}; +} + +function ensureMethod(obj, methodName) { + var fn; + if (obj != null) fn = obj[methodName]; + if (typeof fn !== "function") { + var message = "Object " + util.classString(obj) + " has no method '" + + util.toString(methodName) + "'"; + throw new Promise.TypeError(message); + } + return fn; +} + +function caller(obj) { + var methodName = this.pop(); + var fn = ensureMethod(obj, methodName); + return fn.apply(obj, this); +} +Promise.prototype.call = function (methodName) { + var $_len = arguments.length;var args = new Array(Math.max($_len - 1, 0)); for(var $_i = 1; $_i < $_len; ++$_i) {args[$_i - 1] = arguments[$_i];}; + if (!false) { + if (canEvaluate) { + var maybeCaller = getMethodCaller(methodName); + if (maybeCaller !== null) { + return this._then( + maybeCaller, undefined, undefined, args, undefined); + } + } + } + args.push(methodName); + return this._then(caller, undefined, undefined, args, undefined); +}; + +function namedGetter(obj) { + return obj[this]; +} +function indexedGetter(obj) { + var index = +this; + if (index < 0) index = Math.max(0, index + obj.length); + return obj[index]; +} +Promise.prototype.get = function (propertyName) { + var isIndex = (typeof propertyName === "number"); + var getter; + if (!isIndex) { + if (canEvaluate) { + var maybeGetter = getGetter(propertyName); + getter = maybeGetter !== null ? maybeGetter : namedGetter; + } else { + getter = namedGetter; + } + } else { + getter = indexedGetter; + } + return this._then(getter, undefined, undefined, propertyName, undefined); +}; +}; diff --git a/express-server/node_modules/bluebird/js/release/cancel.js b/express-server/node_modules/bluebird/js/release/cancel.js new file mode 100644 index 00000000..7a12415e --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/cancel.js @@ -0,0 +1,129 @@ +"use strict"; +module.exports = function(Promise, PromiseArray, apiRejection, debug) { +var util = require("./util"); +var tryCatch = util.tryCatch; +var errorObj = util.errorObj; +var async = Promise._async; + +Promise.prototype["break"] = Promise.prototype.cancel = function() { + if (!debug.cancellation()) return this._warn("cancellation is disabled"); + + var promise = this; + var child = promise; + while (promise._isCancellable()) { + if (!promise._cancelBy(child)) { + if (child._isFollowing()) { + child._followee().cancel(); + } else { + child._cancelBranched(); + } + break; + } + + var parent = promise._cancellationParent; + if (parent == null || !parent._isCancellable()) { + if (promise._isFollowing()) { + promise._followee().cancel(); + } else { + promise._cancelBranched(); + } + break; + } else { + if (promise._isFollowing()) promise._followee().cancel(); + promise._setWillBeCancelled(); + child = promise; + promise = parent; + } + } +}; + +Promise.prototype._branchHasCancelled = function() { + this._branchesRemainingToCancel--; +}; + +Promise.prototype._enoughBranchesHaveCancelled = function() { + return this._branchesRemainingToCancel === undefined || + this._branchesRemainingToCancel <= 0; +}; + +Promise.prototype._cancelBy = function(canceller) { + if (canceller === this) { + this._branchesRemainingToCancel = 0; + this._invokeOnCancel(); + return true; + } else { + this._branchHasCancelled(); + if (this._enoughBranchesHaveCancelled()) { + this._invokeOnCancel(); + return true; + } + } + return false; +}; + +Promise.prototype._cancelBranched = function() { + if (this._enoughBranchesHaveCancelled()) { + this._cancel(); + } +}; + +Promise.prototype._cancel = function() { + if (!this._isCancellable()) return; + this._setCancelled(); + async.invoke(this._cancelPromises, this, undefined); +}; + +Promise.prototype._cancelPromises = function() { + if (this._length() > 0) this._settlePromises(); +}; + +Promise.prototype._unsetOnCancel = function() { + this._onCancelField = undefined; +}; + +Promise.prototype._isCancellable = function() { + return this.isPending() && !this._isCancelled(); +}; + +Promise.prototype.isCancellable = function() { + return this.isPending() && !this.isCancelled(); +}; + +Promise.prototype._doInvokeOnCancel = function(onCancelCallback, internalOnly) { + if (util.isArray(onCancelCallback)) { + for (var i = 0; i < onCancelCallback.length; ++i) { + this._doInvokeOnCancel(onCancelCallback[i], internalOnly); + } + } else if (onCancelCallback !== undefined) { + if (typeof onCancelCallback === "function") { + if (!internalOnly) { + var e = tryCatch(onCancelCallback).call(this._boundValue()); + if (e === errorObj) { + this._attachExtraTrace(e.e); + async.throwLater(e.e); + } + } + } else { + onCancelCallback._resultCancelled(this); + } + } +}; + +Promise.prototype._invokeOnCancel = function() { + var onCancelCallback = this._onCancel(); + this._unsetOnCancel(); + async.invoke(this._doInvokeOnCancel, this, onCancelCallback); +}; + +Promise.prototype._invokeInternalOnCancel = function() { + if (this._isCancellable()) { + this._doInvokeOnCancel(this._onCancel(), true); + this._unsetOnCancel(); + } +}; + +Promise.prototype._resultCancelled = function() { + this.cancel(); +}; + +}; diff --git a/express-server/node_modules/bluebird/js/release/catch_filter.js b/express-server/node_modules/bluebird/js/release/catch_filter.js new file mode 100644 index 00000000..0f24ce23 --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/catch_filter.js @@ -0,0 +1,42 @@ +"use strict"; +module.exports = function(NEXT_FILTER) { +var util = require("./util"); +var getKeys = require("./es5").keys; +var tryCatch = util.tryCatch; +var errorObj = util.errorObj; + +function catchFilter(instances, cb, promise) { + return function(e) { + var boundTo = promise._boundValue(); + predicateLoop: for (var i = 0; i < instances.length; ++i) { + var item = instances[i]; + + if (item === Error || + (item != null && item.prototype instanceof Error)) { + if (e instanceof item) { + return tryCatch(cb).call(boundTo, e); + } + } else if (typeof item === "function") { + var matchesPredicate = tryCatch(item).call(boundTo, e); + if (matchesPredicate === errorObj) { + return matchesPredicate; + } else if (matchesPredicate) { + return tryCatch(cb).call(boundTo, e); + } + } else if (util.isObject(e)) { + var keys = getKeys(item); + for (var j = 0; j < keys.length; ++j) { + var key = keys[j]; + if (item[key] != e[key]) { + continue predicateLoop; + } + } + return tryCatch(cb).call(boundTo, e); + } + } + return NEXT_FILTER; + }; +} + +return catchFilter; +}; diff --git a/express-server/node_modules/bluebird/js/release/context.js b/express-server/node_modules/bluebird/js/release/context.js new file mode 100644 index 00000000..c307414f --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/context.js @@ -0,0 +1,69 @@ +"use strict"; +module.exports = function(Promise) { +var longStackTraces = false; +var contextStack = []; + +Promise.prototype._promiseCreated = function() {}; +Promise.prototype._pushContext = function() {}; +Promise.prototype._popContext = function() {return null;}; +Promise._peekContext = Promise.prototype._peekContext = function() {}; + +function Context() { + this._trace = new Context.CapturedTrace(peekContext()); +} +Context.prototype._pushContext = function () { + if (this._trace !== undefined) { + this._trace._promiseCreated = null; + contextStack.push(this._trace); + } +}; + +Context.prototype._popContext = function () { + if (this._trace !== undefined) { + var trace = contextStack.pop(); + var ret = trace._promiseCreated; + trace._promiseCreated = null; + return ret; + } + return null; +}; + +function createContext() { + if (longStackTraces) return new Context(); +} + +function peekContext() { + var lastIndex = contextStack.length - 1; + if (lastIndex >= 0) { + return contextStack[lastIndex]; + } + return undefined; +} +Context.CapturedTrace = null; +Context.create = createContext; +Context.deactivateLongStackTraces = function() {}; +Context.activateLongStackTraces = function() { + var Promise_pushContext = Promise.prototype._pushContext; + var Promise_popContext = Promise.prototype._popContext; + var Promise_PeekContext = Promise._peekContext; + var Promise_peekContext = Promise.prototype._peekContext; + var Promise_promiseCreated = Promise.prototype._promiseCreated; + Context.deactivateLongStackTraces = function() { + Promise.prototype._pushContext = Promise_pushContext; + Promise.prototype._popContext = Promise_popContext; + Promise._peekContext = Promise_PeekContext; + Promise.prototype._peekContext = Promise_peekContext; + Promise.prototype._promiseCreated = Promise_promiseCreated; + longStackTraces = false; + }; + longStackTraces = true; + Promise.prototype._pushContext = Context.prototype._pushContext; + Promise.prototype._popContext = Context.prototype._popContext; + Promise._peekContext = Promise.prototype._peekContext = peekContext; + Promise.prototype._promiseCreated = function() { + var ctx = this._peekContext(); + if (ctx && ctx._promiseCreated == null) ctx._promiseCreated = this; + }; +}; +return Context; +}; diff --git a/express-server/node_modules/bluebird/js/release/debuggability.js b/express-server/node_modules/bluebird/js/release/debuggability.js new file mode 100644 index 00000000..213d4ac6 --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/debuggability.js @@ -0,0 +1,934 @@ +"use strict"; +module.exports = function(Promise, Context) { +var getDomain = Promise._getDomain; +var async = Promise._async; +var Warning = require("./errors").Warning; +var util = require("./util"); +var es5 = require("./es5"); +var canAttachTrace = util.canAttachTrace; +var unhandledRejectionHandled; +var possiblyUnhandledRejection; +var bluebirdFramePattern = + /[\\\/]bluebird[\\\/]js[\\\/](release|debug|instrumented)/; +var nodeFramePattern = /\((?:timers\.js):\d+:\d+\)/; +var parseLinePattern = /[\/<\(](.+?):(\d+):(\d+)\)?\s*$/; +var stackFramePattern = null; +var formatStack = null; +var indentStackFrames = false; +var printWarning; +var debugging = !!(util.env("BLUEBIRD_DEBUG") != 0 && + (false || + util.env("BLUEBIRD_DEBUG") || + util.env("NODE_ENV") === "development")); + +var warnings = !!(util.env("BLUEBIRD_WARNINGS") != 0 && + (debugging || util.env("BLUEBIRD_WARNINGS"))); + +var longStackTraces = !!(util.env("BLUEBIRD_LONG_STACK_TRACES") != 0 && + (debugging || util.env("BLUEBIRD_LONG_STACK_TRACES"))); + +var wForgottenReturn = util.env("BLUEBIRD_W_FORGOTTEN_RETURN") != 0 && + (warnings || !!util.env("BLUEBIRD_W_FORGOTTEN_RETURN")); + +Promise.prototype.suppressUnhandledRejections = function() { + var target = this._target(); + target._bitField = ((target._bitField & (~1048576)) | + 524288); +}; + +Promise.prototype._ensurePossibleRejectionHandled = function () { + if ((this._bitField & 524288) !== 0) return; + this._setRejectionIsUnhandled(); + var self = this; + setTimeout(function() { + self._notifyUnhandledRejection(); + }, 1); +}; + +Promise.prototype._notifyUnhandledRejectionIsHandled = function () { + fireRejectionEvent("rejectionHandled", + unhandledRejectionHandled, undefined, this); +}; + +Promise.prototype._setReturnedNonUndefined = function() { + this._bitField = this._bitField | 268435456; +}; + +Promise.prototype._returnedNonUndefined = function() { + return (this._bitField & 268435456) !== 0; +}; + +Promise.prototype._notifyUnhandledRejection = function () { + if (this._isRejectionUnhandled()) { + var reason = this._settledValue(); + this._setUnhandledRejectionIsNotified(); + fireRejectionEvent("unhandledRejection", + possiblyUnhandledRejection, reason, this); + } +}; + +Promise.prototype._setUnhandledRejectionIsNotified = function () { + this._bitField = this._bitField | 262144; +}; + +Promise.prototype._unsetUnhandledRejectionIsNotified = function () { + this._bitField = this._bitField & (~262144); +}; + +Promise.prototype._isUnhandledRejectionNotified = function () { + return (this._bitField & 262144) > 0; +}; + +Promise.prototype._setRejectionIsUnhandled = function () { + this._bitField = this._bitField | 1048576; +}; + +Promise.prototype._unsetRejectionIsUnhandled = function () { + this._bitField = this._bitField & (~1048576); + if (this._isUnhandledRejectionNotified()) { + this._unsetUnhandledRejectionIsNotified(); + this._notifyUnhandledRejectionIsHandled(); + } +}; + +Promise.prototype._isRejectionUnhandled = function () { + return (this._bitField & 1048576) > 0; +}; + +Promise.prototype._warn = function(message, shouldUseOwnTrace, promise) { + return warn(message, shouldUseOwnTrace, promise || this); +}; + +Promise.onPossiblyUnhandledRejection = function (fn) { + var domain = getDomain(); + possiblyUnhandledRejection = + typeof fn === "function" ? (domain === null ? + fn : util.domainBind(domain, fn)) + : undefined; +}; + +Promise.onUnhandledRejectionHandled = function (fn) { + var domain = getDomain(); + unhandledRejectionHandled = + typeof fn === "function" ? (domain === null ? + fn : util.domainBind(domain, fn)) + : undefined; +}; + +var disableLongStackTraces = function() {}; +Promise.longStackTraces = function () { + if (async.haveItemsQueued() && !config.longStackTraces) { + throw new Error("cannot enable long stack traces after promises have been created\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + if (!config.longStackTraces && longStackTracesIsSupported()) { + var Promise_captureStackTrace = Promise.prototype._captureStackTrace; + var Promise_attachExtraTrace = Promise.prototype._attachExtraTrace; + var Promise_dereferenceTrace = Promise.prototype._dereferenceTrace; + config.longStackTraces = true; + disableLongStackTraces = function() { + if (async.haveItemsQueued() && !config.longStackTraces) { + throw new Error("cannot enable long stack traces after promises have been created\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + Promise.prototype._captureStackTrace = Promise_captureStackTrace; + Promise.prototype._attachExtraTrace = Promise_attachExtraTrace; + Promise.prototype._dereferenceTrace = Promise_dereferenceTrace; + Context.deactivateLongStackTraces(); + async.enableTrampoline(); + config.longStackTraces = false; + }; + Promise.prototype._captureStackTrace = longStackTracesCaptureStackTrace; + Promise.prototype._attachExtraTrace = longStackTracesAttachExtraTrace; + Promise.prototype._dereferenceTrace = longStackTracesDereferenceTrace; + Context.activateLongStackTraces(); + async.disableTrampolineIfNecessary(); + } +}; + +Promise.hasLongStackTraces = function () { + return config.longStackTraces && longStackTracesIsSupported(); +}; + +var fireDomEvent = (function() { + try { + if (typeof CustomEvent === "function") { + var event = new CustomEvent("CustomEvent"); + util.global.dispatchEvent(event); + return function(name, event) { + var eventData = { + detail: event, + cancelable: true + }; + es5.defineProperty( + eventData, "promise", {value: event.promise}); + es5.defineProperty(eventData, "reason", {value: event.reason}); + var domEvent = new CustomEvent(name.toLowerCase(), eventData); + return !util.global.dispatchEvent(domEvent); + }; + } else if (typeof Event === "function") { + var event = new Event("CustomEvent"); + util.global.dispatchEvent(event); + return function(name, event) { + var domEvent = new Event(name.toLowerCase(), { + cancelable: true + }); + domEvent.detail = event; + es5.defineProperty(domEvent, "promise", {value: event.promise}); + es5.defineProperty(domEvent, "reason", {value: event.reason}); + return !util.global.dispatchEvent(domEvent); + }; + } else { + var event = document.createEvent("CustomEvent"); + event.initCustomEvent("testingtheevent", false, true, {}); + util.global.dispatchEvent(event); + return function(name, event) { + var domEvent = document.createEvent("CustomEvent"); + domEvent.initCustomEvent(name.toLowerCase(), false, true, + event); + return !util.global.dispatchEvent(domEvent); + }; + } + } catch (e) {} + return function() { + return false; + }; +})(); + +var fireGlobalEvent = (function() { + if (util.isNode) { + return function() { + return process.emit.apply(process, arguments); + }; + } else { + if (!util.global) { + return function() { + return false; + }; + } + return function(name) { + var methodName = "on" + name.toLowerCase(); + var method = util.global[methodName]; + if (!method) return false; + method.apply(util.global, [].slice.call(arguments, 1)); + return true; + }; + } +})(); + +function generatePromiseLifecycleEventObject(name, promise) { + return {promise: promise}; +} + +var eventToObjectGenerator = { + promiseCreated: generatePromiseLifecycleEventObject, + promiseFulfilled: generatePromiseLifecycleEventObject, + promiseRejected: generatePromiseLifecycleEventObject, + promiseResolved: generatePromiseLifecycleEventObject, + promiseCancelled: generatePromiseLifecycleEventObject, + promiseChained: function(name, promise, child) { + return {promise: promise, child: child}; + }, + warning: function(name, warning) { + return {warning: warning}; + }, + unhandledRejection: function (name, reason, promise) { + return {reason: reason, promise: promise}; + }, + rejectionHandled: generatePromiseLifecycleEventObject +}; + +var activeFireEvent = function (name) { + var globalEventFired = false; + try { + globalEventFired = fireGlobalEvent.apply(null, arguments); + } catch (e) { + async.throwLater(e); + globalEventFired = true; + } + + var domEventFired = false; + try { + domEventFired = fireDomEvent(name, + eventToObjectGenerator[name].apply(null, arguments)); + } catch (e) { + async.throwLater(e); + domEventFired = true; + } + + return domEventFired || globalEventFired; +}; + +Promise.config = function(opts) { + opts = Object(opts); + if ("longStackTraces" in opts) { + if (opts.longStackTraces) { + Promise.longStackTraces(); + } else if (!opts.longStackTraces && Promise.hasLongStackTraces()) { + disableLongStackTraces(); + } + } + if ("warnings" in opts) { + var warningsOption = opts.warnings; + config.warnings = !!warningsOption; + wForgottenReturn = config.warnings; + + if (util.isObject(warningsOption)) { + if ("wForgottenReturn" in warningsOption) { + wForgottenReturn = !!warningsOption.wForgottenReturn; + } + } + } + if ("cancellation" in opts && opts.cancellation && !config.cancellation) { + if (async.haveItemsQueued()) { + throw new Error( + "cannot enable cancellation after promises are in use"); + } + Promise.prototype._clearCancellationData = + cancellationClearCancellationData; + Promise.prototype._propagateFrom = cancellationPropagateFrom; + Promise.prototype._onCancel = cancellationOnCancel; + Promise.prototype._setOnCancel = cancellationSetOnCancel; + Promise.prototype._attachCancellationCallback = + cancellationAttachCancellationCallback; + Promise.prototype._execute = cancellationExecute; + propagateFromFunction = cancellationPropagateFrom; + config.cancellation = true; + } + if ("monitoring" in opts) { + if (opts.monitoring && !config.monitoring) { + config.monitoring = true; + Promise.prototype._fireEvent = activeFireEvent; + } else if (!opts.monitoring && config.monitoring) { + config.monitoring = false; + Promise.prototype._fireEvent = defaultFireEvent; + } + } + return Promise; +}; + +function defaultFireEvent() { return false; } + +Promise.prototype._fireEvent = defaultFireEvent; +Promise.prototype._execute = function(executor, resolve, reject) { + try { + executor(resolve, reject); + } catch (e) { + return e; + } +}; +Promise.prototype._onCancel = function () {}; +Promise.prototype._setOnCancel = function (handler) { ; }; +Promise.prototype._attachCancellationCallback = function(onCancel) { + ; +}; +Promise.prototype._captureStackTrace = function () {}; +Promise.prototype._attachExtraTrace = function () {}; +Promise.prototype._dereferenceTrace = function () {}; +Promise.prototype._clearCancellationData = function() {}; +Promise.prototype._propagateFrom = function (parent, flags) { + ; + ; +}; + +function cancellationExecute(executor, resolve, reject) { + var promise = this; + try { + executor(resolve, reject, function(onCancel) { + if (typeof onCancel !== "function") { + throw new TypeError("onCancel must be a function, got: " + + util.toString(onCancel)); + } + promise._attachCancellationCallback(onCancel); + }); + } catch (e) { + return e; + } +} + +function cancellationAttachCancellationCallback(onCancel) { + if (!this._isCancellable()) return this; + + var previousOnCancel = this._onCancel(); + if (previousOnCancel !== undefined) { + if (util.isArray(previousOnCancel)) { + previousOnCancel.push(onCancel); + } else { + this._setOnCancel([previousOnCancel, onCancel]); + } + } else { + this._setOnCancel(onCancel); + } +} + +function cancellationOnCancel() { + return this._onCancelField; +} + +function cancellationSetOnCancel(onCancel) { + this._onCancelField = onCancel; +} + +function cancellationClearCancellationData() { + this._cancellationParent = undefined; + this._onCancelField = undefined; +} + +function cancellationPropagateFrom(parent, flags) { + if ((flags & 1) !== 0) { + this._cancellationParent = parent; + var branchesRemainingToCancel = parent._branchesRemainingToCancel; + if (branchesRemainingToCancel === undefined) { + branchesRemainingToCancel = 0; + } + parent._branchesRemainingToCancel = branchesRemainingToCancel + 1; + } + if ((flags & 2) !== 0 && parent._isBound()) { + this._setBoundTo(parent._boundTo); + } +} + +function bindingPropagateFrom(parent, flags) { + if ((flags & 2) !== 0 && parent._isBound()) { + this._setBoundTo(parent._boundTo); + } +} +var propagateFromFunction = bindingPropagateFrom; + +function boundValueFunction() { + var ret = this._boundTo; + if (ret !== undefined) { + if (ret instanceof Promise) { + if (ret.isFulfilled()) { + return ret.value(); + } else { + return undefined; + } + } + } + return ret; +} + +function longStackTracesCaptureStackTrace() { + this._trace = new CapturedTrace(this._peekContext()); +} + +function longStackTracesAttachExtraTrace(error, ignoreSelf) { + if (canAttachTrace(error)) { + var trace = this._trace; + if (trace !== undefined) { + if (ignoreSelf) trace = trace._parent; + } + if (trace !== undefined) { + trace.attachExtraTrace(error); + } else if (!error.__stackCleaned__) { + var parsed = parseStackAndMessage(error); + util.notEnumerableProp(error, "stack", + parsed.message + "\n" + parsed.stack.join("\n")); + util.notEnumerableProp(error, "__stackCleaned__", true); + } + } +} + +function longStackTracesDereferenceTrace() { + this._trace = undefined; +} + +function checkForgottenReturns(returnValue, promiseCreated, name, promise, + parent) { + if (returnValue === undefined && promiseCreated !== null && + wForgottenReturn) { + if (parent !== undefined && parent._returnedNonUndefined()) return; + if ((promise._bitField & 65535) === 0) return; + + if (name) name = name + " "; + var handlerLine = ""; + var creatorLine = ""; + if (promiseCreated._trace) { + var traceLines = promiseCreated._trace.stack.split("\n"); + var stack = cleanStack(traceLines); + for (var i = stack.length - 1; i >= 0; --i) { + var line = stack[i]; + if (!nodeFramePattern.test(line)) { + var lineMatches = line.match(parseLinePattern); + if (lineMatches) { + handlerLine = "at " + lineMatches[1] + + ":" + lineMatches[2] + ":" + lineMatches[3] + " "; + } + break; + } + } + + if (stack.length > 0) { + var firstUserLine = stack[0]; + for (var i = 0; i < traceLines.length; ++i) { + + if (traceLines[i] === firstUserLine) { + if (i > 0) { + creatorLine = "\n" + traceLines[i - 1]; + } + break; + } + } + + } + } + var msg = "a promise was created in a " + name + + "handler " + handlerLine + "but was not returned from it, " + + "see http://goo.gl/rRqMUw" + + creatorLine; + promise._warn(msg, true, promiseCreated); + } +} + +function deprecated(name, replacement) { + var message = name + + " is deprecated and will be removed in a future version."; + if (replacement) message += " Use " + replacement + " instead."; + return warn(message); +} + +function warn(message, shouldUseOwnTrace, promise) { + if (!config.warnings) return; + var warning = new Warning(message); + var ctx; + if (shouldUseOwnTrace) { + promise._attachExtraTrace(warning); + } else if (config.longStackTraces && (ctx = Promise._peekContext())) { + ctx.attachExtraTrace(warning); + } else { + var parsed = parseStackAndMessage(warning); + warning.stack = parsed.message + "\n" + parsed.stack.join("\n"); + } + + if (!activeFireEvent("warning", warning)) { + formatAndLogError(warning, "", true); + } +} + +function reconstructStack(message, stacks) { + for (var i = 0; i < stacks.length - 1; ++i) { + stacks[i].push("From previous event:"); + stacks[i] = stacks[i].join("\n"); + } + if (i < stacks.length) { + stacks[i] = stacks[i].join("\n"); + } + return message + "\n" + stacks.join("\n"); +} + +function removeDuplicateOrEmptyJumps(stacks) { + for (var i = 0; i < stacks.length; ++i) { + if (stacks[i].length === 0 || + ((i + 1 < stacks.length) && stacks[i][0] === stacks[i+1][0])) { + stacks.splice(i, 1); + i--; + } + } +} + +function removeCommonRoots(stacks) { + var current = stacks[0]; + for (var i = 1; i < stacks.length; ++i) { + var prev = stacks[i]; + var currentLastIndex = current.length - 1; + var currentLastLine = current[currentLastIndex]; + var commonRootMeetPoint = -1; + + for (var j = prev.length - 1; j >= 0; --j) { + if (prev[j] === currentLastLine) { + commonRootMeetPoint = j; + break; + } + } + + for (var j = commonRootMeetPoint; j >= 0; --j) { + var line = prev[j]; + if (current[currentLastIndex] === line) { + current.pop(); + currentLastIndex--; + } else { + break; + } + } + current = prev; + } +} + +function cleanStack(stack) { + var ret = []; + for (var i = 0; i < stack.length; ++i) { + var line = stack[i]; + var isTraceLine = " (No stack trace)" === line || + stackFramePattern.test(line); + var isInternalFrame = isTraceLine && shouldIgnore(line); + if (isTraceLine && !isInternalFrame) { + if (indentStackFrames && line.charAt(0) !== " ") { + line = " " + line; + } + ret.push(line); + } + } + return ret; +} + +function stackFramesAsArray(error) { + var stack = error.stack.replace(/\s+$/g, "").split("\n"); + for (var i = 0; i < stack.length; ++i) { + var line = stack[i]; + if (" (No stack trace)" === line || stackFramePattern.test(line)) { + break; + } + } + if (i > 0 && error.name != "SyntaxError") { + stack = stack.slice(i); + } + return stack; +} + +function parseStackAndMessage(error) { + var stack = error.stack; + var message = error.toString(); + stack = typeof stack === "string" && stack.length > 0 + ? stackFramesAsArray(error) : [" (No stack trace)"]; + return { + message: message, + stack: error.name == "SyntaxError" ? stack : cleanStack(stack) + }; +} + +function formatAndLogError(error, title, isSoft) { + if (typeof console !== "undefined") { + var message; + if (util.isObject(error)) { + var stack = error.stack; + message = title + formatStack(stack, error); + } else { + message = title + String(error); + } + if (typeof printWarning === "function") { + printWarning(message, isSoft); + } else if (typeof console.log === "function" || + typeof console.log === "object") { + console.log(message); + } + } +} + +function fireRejectionEvent(name, localHandler, reason, promise) { + var localEventFired = false; + try { + if (typeof localHandler === "function") { + localEventFired = true; + if (name === "rejectionHandled") { + localHandler(promise); + } else { + localHandler(reason, promise); + } + } + } catch (e) { + async.throwLater(e); + } + + if (name === "unhandledRejection") { + if (!activeFireEvent(name, reason, promise) && !localEventFired) { + formatAndLogError(reason, "Unhandled rejection "); + } + } else { + activeFireEvent(name, promise); + } +} + +function formatNonError(obj) { + var str; + if (typeof obj === "function") { + str = "[function " + + (obj.name || "anonymous") + + "]"; + } else { + str = obj && typeof obj.toString === "function" + ? obj.toString() : util.toString(obj); + var ruselessToString = /\[object [a-zA-Z0-9$_]+\]/; + if (ruselessToString.test(str)) { + try { + var newStr = JSON.stringify(obj); + str = newStr; + } + catch(e) { + + } + } + if (str.length === 0) { + str = "(empty array)"; + } + } + return ("(<" + snip(str) + ">, no stack trace)"); +} + +function snip(str) { + var maxChars = 41; + if (str.length < maxChars) { + return str; + } + return str.substr(0, maxChars - 3) + "..."; +} + +function longStackTracesIsSupported() { + return typeof captureStackTrace === "function"; +} + +var shouldIgnore = function() { return false; }; +var parseLineInfoRegex = /[\/<\(]([^:\/]+):(\d+):(?:\d+)\)?\s*$/; +function parseLineInfo(line) { + var matches = line.match(parseLineInfoRegex); + if (matches) { + return { + fileName: matches[1], + line: parseInt(matches[2], 10) + }; + } +} + +function setBounds(firstLineError, lastLineError) { + if (!longStackTracesIsSupported()) return; + var firstStackLines = firstLineError.stack.split("\n"); + var lastStackLines = lastLineError.stack.split("\n"); + var firstIndex = -1; + var lastIndex = -1; + var firstFileName; + var lastFileName; + for (var i = 0; i < firstStackLines.length; ++i) { + var result = parseLineInfo(firstStackLines[i]); + if (result) { + firstFileName = result.fileName; + firstIndex = result.line; + break; + } + } + for (var i = 0; i < lastStackLines.length; ++i) { + var result = parseLineInfo(lastStackLines[i]); + if (result) { + lastFileName = result.fileName; + lastIndex = result.line; + break; + } + } + if (firstIndex < 0 || lastIndex < 0 || !firstFileName || !lastFileName || + firstFileName !== lastFileName || firstIndex >= lastIndex) { + return; + } + + shouldIgnore = function(line) { + if (bluebirdFramePattern.test(line)) return true; + var info = parseLineInfo(line); + if (info) { + if (info.fileName === firstFileName && + (firstIndex <= info.line && info.line <= lastIndex)) { + return true; + } + } + return false; + }; +} + +function CapturedTrace(parent) { + this._parent = parent; + this._promisesCreated = 0; + var length = this._length = 1 + (parent === undefined ? 0 : parent._length); + captureStackTrace(this, CapturedTrace); + if (length > 32) this.uncycle(); +} +util.inherits(CapturedTrace, Error); +Context.CapturedTrace = CapturedTrace; + +CapturedTrace.prototype.uncycle = function() { + var length = this._length; + if (length < 2) return; + var nodes = []; + var stackToIndex = {}; + + for (var i = 0, node = this; node !== undefined; ++i) { + nodes.push(node); + node = node._parent; + } + length = this._length = i; + for (var i = length - 1; i >= 0; --i) { + var stack = nodes[i].stack; + if (stackToIndex[stack] === undefined) { + stackToIndex[stack] = i; + } + } + for (var i = 0; i < length; ++i) { + var currentStack = nodes[i].stack; + var index = stackToIndex[currentStack]; + if (index !== undefined && index !== i) { + if (index > 0) { + nodes[index - 1]._parent = undefined; + nodes[index - 1]._length = 1; + } + nodes[i]._parent = undefined; + nodes[i]._length = 1; + var cycleEdgeNode = i > 0 ? nodes[i - 1] : this; + + if (index < length - 1) { + cycleEdgeNode._parent = nodes[index + 1]; + cycleEdgeNode._parent.uncycle(); + cycleEdgeNode._length = + cycleEdgeNode._parent._length + 1; + } else { + cycleEdgeNode._parent = undefined; + cycleEdgeNode._length = 1; + } + var currentChildLength = cycleEdgeNode._length + 1; + for (var j = i - 2; j >= 0; --j) { + nodes[j]._length = currentChildLength; + currentChildLength++; + } + return; + } + } +}; + +CapturedTrace.prototype.attachExtraTrace = function(error) { + if (error.__stackCleaned__) return; + this.uncycle(); + var parsed = parseStackAndMessage(error); + var message = parsed.message; + var stacks = [parsed.stack]; + + var trace = this; + while (trace !== undefined) { + stacks.push(cleanStack(trace.stack.split("\n"))); + trace = trace._parent; + } + removeCommonRoots(stacks); + removeDuplicateOrEmptyJumps(stacks); + util.notEnumerableProp(error, "stack", reconstructStack(message, stacks)); + util.notEnumerableProp(error, "__stackCleaned__", true); +}; + +var captureStackTrace = (function stackDetection() { + var v8stackFramePattern = /^\s*at\s*/; + var v8stackFormatter = function(stack, error) { + if (typeof stack === "string") return stack; + + if (error.name !== undefined && + error.message !== undefined) { + return error.toString(); + } + return formatNonError(error); + }; + + if (typeof Error.stackTraceLimit === "number" && + typeof Error.captureStackTrace === "function") { + Error.stackTraceLimit += 6; + stackFramePattern = v8stackFramePattern; + formatStack = v8stackFormatter; + var captureStackTrace = Error.captureStackTrace; + + shouldIgnore = function(line) { + return bluebirdFramePattern.test(line); + }; + return function(receiver, ignoreUntil) { + Error.stackTraceLimit += 6; + captureStackTrace(receiver, ignoreUntil); + Error.stackTraceLimit -= 6; + }; + } + var err = new Error(); + + if (typeof err.stack === "string" && + err.stack.split("\n")[0].indexOf("stackDetection@") >= 0) { + stackFramePattern = /@/; + formatStack = v8stackFormatter; + indentStackFrames = true; + return function captureStackTrace(o) { + o.stack = new Error().stack; + }; + } + + var hasStackAfterThrow; + try { throw new Error(); } + catch(e) { + hasStackAfterThrow = ("stack" in e); + } + if (!("stack" in err) && hasStackAfterThrow && + typeof Error.stackTraceLimit === "number") { + stackFramePattern = v8stackFramePattern; + formatStack = v8stackFormatter; + return function captureStackTrace(o) { + Error.stackTraceLimit += 6; + try { throw new Error(); } + catch(e) { o.stack = e.stack; } + Error.stackTraceLimit -= 6; + }; + } + + formatStack = function(stack, error) { + if (typeof stack === "string") return stack; + + if ((typeof error === "object" || + typeof error === "function") && + error.name !== undefined && + error.message !== undefined) { + return error.toString(); + } + return formatNonError(error); + }; + + return null; + +})([]); + +if (typeof console !== "undefined" && typeof console.warn !== "undefined") { + printWarning = function (message) { + console.warn(message); + }; + if (util.isNode && process.stderr.isTTY) { + printWarning = function(message, isSoft) { + var color = isSoft ? "\u001b[33m" : "\u001b[31m"; + console.warn(color + message + "\u001b[0m\n"); + }; + } else if (!util.isNode && typeof (new Error().stack) === "string") { + printWarning = function(message, isSoft) { + console.warn("%c" + message, + isSoft ? "color: darkorange" : "color: red"); + }; + } +} + +var config = { + warnings: warnings, + longStackTraces: false, + cancellation: false, + monitoring: false +}; + +if (longStackTraces) Promise.longStackTraces(); + +return { + longStackTraces: function() { + return config.longStackTraces; + }, + warnings: function() { + return config.warnings; + }, + cancellation: function() { + return config.cancellation; + }, + monitoring: function() { + return config.monitoring; + }, + propagateFromFunction: function() { + return propagateFromFunction; + }, + boundValueFunction: function() { + return boundValueFunction; + }, + checkForgottenReturns: checkForgottenReturns, + setBounds: setBounds, + warn: warn, + deprecated: deprecated, + CapturedTrace: CapturedTrace, + fireDomEvent: fireDomEvent, + fireGlobalEvent: fireGlobalEvent +}; +}; diff --git a/express-server/node_modules/bluebird/js/release/direct_resolve.js b/express-server/node_modules/bluebird/js/release/direct_resolve.js new file mode 100644 index 00000000..a8902982 --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/direct_resolve.js @@ -0,0 +1,46 @@ +"use strict"; +module.exports = function(Promise) { +function returner() { + return this.value; +} +function thrower() { + throw this.reason; +} + +Promise.prototype["return"] = +Promise.prototype.thenReturn = function (value) { + if (value instanceof Promise) value.suppressUnhandledRejections(); + return this._then( + returner, undefined, undefined, {value: value}, undefined); +}; + +Promise.prototype["throw"] = +Promise.prototype.thenThrow = function (reason) { + return this._then( + thrower, undefined, undefined, {reason: reason}, undefined); +}; + +Promise.prototype.catchThrow = function (reason) { + if (arguments.length <= 1) { + return this._then( + undefined, thrower, undefined, {reason: reason}, undefined); + } else { + var _reason = arguments[1]; + var handler = function() {throw _reason;}; + return this.caught(reason, handler); + } +}; + +Promise.prototype.catchReturn = function (value) { + if (arguments.length <= 1) { + if (value instanceof Promise) value.suppressUnhandledRejections(); + return this._then( + undefined, returner, undefined, {value: value}, undefined); + } else { + var _value = arguments[1]; + if (_value instanceof Promise) _value.suppressUnhandledRejections(); + var handler = function() {return _value;}; + return this.caught(value, handler); + } +}; +}; diff --git a/express-server/node_modules/bluebird/js/release/each.js b/express-server/node_modules/bluebird/js/release/each.js new file mode 100644 index 00000000..e4f3d05b --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/each.js @@ -0,0 +1,30 @@ +"use strict"; +module.exports = function(Promise, INTERNAL) { +var PromiseReduce = Promise.reduce; +var PromiseAll = Promise.all; + +function promiseAllThis() { + return PromiseAll(this); +} + +function PromiseMapSeries(promises, fn) { + return PromiseReduce(promises, fn, INTERNAL, INTERNAL); +} + +Promise.prototype.each = function (fn) { + return PromiseReduce(this, fn, INTERNAL, 0) + ._then(promiseAllThis, undefined, undefined, this, undefined); +}; + +Promise.prototype.mapSeries = function (fn) { + return PromiseReduce(this, fn, INTERNAL, INTERNAL); +}; + +Promise.each = function (promises, fn) { + return PromiseReduce(promises, fn, INTERNAL, 0) + ._then(promiseAllThis, undefined, undefined, promises, undefined); +}; + +Promise.mapSeries = PromiseMapSeries; +}; + diff --git a/express-server/node_modules/bluebird/js/release/errors.js b/express-server/node_modules/bluebird/js/release/errors.js new file mode 100644 index 00000000..f62f323e --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/errors.js @@ -0,0 +1,116 @@ +"use strict"; +var es5 = require("./es5"); +var Objectfreeze = es5.freeze; +var util = require("./util"); +var inherits = util.inherits; +var notEnumerableProp = util.notEnumerableProp; + +function subError(nameProperty, defaultMessage) { + function SubError(message) { + if (!(this instanceof SubError)) return new SubError(message); + notEnumerableProp(this, "message", + typeof message === "string" ? message : defaultMessage); + notEnumerableProp(this, "name", nameProperty); + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } else { + Error.call(this); + } + } + inherits(SubError, Error); + return SubError; +} + +var _TypeError, _RangeError; +var Warning = subError("Warning", "warning"); +var CancellationError = subError("CancellationError", "cancellation error"); +var TimeoutError = subError("TimeoutError", "timeout error"); +var AggregateError = subError("AggregateError", "aggregate error"); +try { + _TypeError = TypeError; + _RangeError = RangeError; +} catch(e) { + _TypeError = subError("TypeError", "type error"); + _RangeError = subError("RangeError", "range error"); +} + +var methods = ("join pop push shift unshift slice filter forEach some " + + "every map indexOf lastIndexOf reduce reduceRight sort reverse").split(" "); + +for (var i = 0; i < methods.length; ++i) { + if (typeof Array.prototype[methods[i]] === "function") { + AggregateError.prototype[methods[i]] = Array.prototype[methods[i]]; + } +} + +es5.defineProperty(AggregateError.prototype, "length", { + value: 0, + configurable: false, + writable: true, + enumerable: true +}); +AggregateError.prototype["isOperational"] = true; +var level = 0; +AggregateError.prototype.toString = function() { + var indent = Array(level * 4 + 1).join(" "); + var ret = "\n" + indent + "AggregateError of:" + "\n"; + level++; + indent = Array(level * 4 + 1).join(" "); + for (var i = 0; i < this.length; ++i) { + var str = this[i] === this ? "[Circular AggregateError]" : this[i] + ""; + var lines = str.split("\n"); + for (var j = 0; j < lines.length; ++j) { + lines[j] = indent + lines[j]; + } + str = lines.join("\n"); + ret += str + "\n"; + } + level--; + return ret; +}; + +function OperationalError(message) { + if (!(this instanceof OperationalError)) + return new OperationalError(message); + notEnumerableProp(this, "name", "OperationalError"); + notEnumerableProp(this, "message", message); + this.cause = message; + this["isOperational"] = true; + + if (message instanceof Error) { + notEnumerableProp(this, "message", message.message); + notEnumerableProp(this, "stack", message.stack); + } else if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + +} +inherits(OperationalError, Error); + +var errorTypes = Error["__BluebirdErrorTypes__"]; +if (!errorTypes) { + errorTypes = Objectfreeze({ + CancellationError: CancellationError, + TimeoutError: TimeoutError, + OperationalError: OperationalError, + RejectionError: OperationalError, + AggregateError: AggregateError + }); + es5.defineProperty(Error, "__BluebirdErrorTypes__", { + value: errorTypes, + writable: false, + enumerable: false, + configurable: false + }); +} + +module.exports = { + Error: Error, + TypeError: _TypeError, + RangeError: _RangeError, + CancellationError: errorTypes.CancellationError, + OperationalError: errorTypes.OperationalError, + TimeoutError: errorTypes.TimeoutError, + AggregateError: errorTypes.AggregateError, + Warning: Warning +}; diff --git a/express-server/node_modules/bluebird/js/release/es5.js b/express-server/node_modules/bluebird/js/release/es5.js new file mode 100644 index 00000000..ea41d5a5 --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/es5.js @@ -0,0 +1,80 @@ +var isES5 = (function(){ + "use strict"; + return this === undefined; +})(); + +if (isES5) { + module.exports = { + freeze: Object.freeze, + defineProperty: Object.defineProperty, + getDescriptor: Object.getOwnPropertyDescriptor, + keys: Object.keys, + names: Object.getOwnPropertyNames, + getPrototypeOf: Object.getPrototypeOf, + isArray: Array.isArray, + isES5: isES5, + propertyIsWritable: function(obj, prop) { + var descriptor = Object.getOwnPropertyDescriptor(obj, prop); + return !!(!descriptor || descriptor.writable || descriptor.set); + } + }; +} else { + var has = {}.hasOwnProperty; + var str = {}.toString; + var proto = {}.constructor.prototype; + + var ObjectKeys = function (o) { + var ret = []; + for (var key in o) { + if (has.call(o, key)) { + ret.push(key); + } + } + return ret; + }; + + var ObjectGetDescriptor = function(o, key) { + return {value: o[key]}; + }; + + var ObjectDefineProperty = function (o, key, desc) { + o[key] = desc.value; + return o; + }; + + var ObjectFreeze = function (obj) { + return obj; + }; + + var ObjectGetPrototypeOf = function (obj) { + try { + return Object(obj).constructor.prototype; + } + catch (e) { + return proto; + } + }; + + var ArrayIsArray = function (obj) { + try { + return str.call(obj) === "[object Array]"; + } + catch(e) { + return false; + } + }; + + module.exports = { + isArray: ArrayIsArray, + keys: ObjectKeys, + names: ObjectKeys, + defineProperty: ObjectDefineProperty, + getDescriptor: ObjectGetDescriptor, + freeze: ObjectFreeze, + getPrototypeOf: ObjectGetPrototypeOf, + isES5: isES5, + propertyIsWritable: function() { + return true; + } + }; +} diff --git a/express-server/node_modules/bluebird/js/release/filter.js b/express-server/node_modules/bluebird/js/release/filter.js new file mode 100644 index 00000000..ed57bf01 --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/filter.js @@ -0,0 +1,12 @@ +"use strict"; +module.exports = function(Promise, INTERNAL) { +var PromiseMap = Promise.map; + +Promise.prototype.filter = function (fn, options) { + return PromiseMap(this, fn, options, INTERNAL); +}; + +Promise.filter = function (promises, fn, options) { + return PromiseMap(promises, fn, options, INTERNAL); +}; +}; diff --git a/express-server/node_modules/bluebird/js/release/finally.js b/express-server/node_modules/bluebird/js/release/finally.js new file mode 100644 index 00000000..d57444be --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/finally.js @@ -0,0 +1,146 @@ +"use strict"; +module.exports = function(Promise, tryConvertToPromise, NEXT_FILTER) { +var util = require("./util"); +var CancellationError = Promise.CancellationError; +var errorObj = util.errorObj; +var catchFilter = require("./catch_filter")(NEXT_FILTER); + +function PassThroughHandlerContext(promise, type, handler) { + this.promise = promise; + this.type = type; + this.handler = handler; + this.called = false; + this.cancelPromise = null; +} + +PassThroughHandlerContext.prototype.isFinallyHandler = function() { + return this.type === 0; +}; + +function FinallyHandlerCancelReaction(finallyHandler) { + this.finallyHandler = finallyHandler; +} + +FinallyHandlerCancelReaction.prototype._resultCancelled = function() { + checkCancel(this.finallyHandler); +}; + +function checkCancel(ctx, reason) { + if (ctx.cancelPromise != null) { + if (arguments.length > 1) { + ctx.cancelPromise._reject(reason); + } else { + ctx.cancelPromise._cancel(); + } + ctx.cancelPromise = null; + return true; + } + return false; +} + +function succeed() { + return finallyHandler.call(this, this.promise._target()._settledValue()); +} +function fail(reason) { + if (checkCancel(this, reason)) return; + errorObj.e = reason; + return errorObj; +} +function finallyHandler(reasonOrValue) { + var promise = this.promise; + var handler = this.handler; + + if (!this.called) { + this.called = true; + var ret = this.isFinallyHandler() + ? handler.call(promise._boundValue()) + : handler.call(promise._boundValue(), reasonOrValue); + if (ret === NEXT_FILTER) { + return ret; + } else if (ret !== undefined) { + promise._setReturnedNonUndefined(); + var maybePromise = tryConvertToPromise(ret, promise); + if (maybePromise instanceof Promise) { + if (this.cancelPromise != null) { + if (maybePromise._isCancelled()) { + var reason = + new CancellationError("late cancellation observer"); + promise._attachExtraTrace(reason); + errorObj.e = reason; + return errorObj; + } else if (maybePromise.isPending()) { + maybePromise._attachCancellationCallback( + new FinallyHandlerCancelReaction(this)); + } + } + return maybePromise._then( + succeed, fail, undefined, this, undefined); + } + } + } + + if (promise.isRejected()) { + checkCancel(this); + errorObj.e = reasonOrValue; + return errorObj; + } else { + checkCancel(this); + return reasonOrValue; + } +} + +Promise.prototype._passThrough = function(handler, type, success, fail) { + if (typeof handler !== "function") return this.then(); + return this._then(success, + fail, + undefined, + new PassThroughHandlerContext(this, type, handler), + undefined); +}; + +Promise.prototype.lastly = +Promise.prototype["finally"] = function (handler) { + return this._passThrough(handler, + 0, + finallyHandler, + finallyHandler); +}; + + +Promise.prototype.tap = function (handler) { + return this._passThrough(handler, 1, finallyHandler); +}; + +Promise.prototype.tapCatch = function (handlerOrPredicate) { + var len = arguments.length; + if(len === 1) { + return this._passThrough(handlerOrPredicate, + 1, + undefined, + finallyHandler); + } else { + var catchInstances = new Array(len - 1), + j = 0, i; + for (i = 0; i < len - 1; ++i) { + var item = arguments[i]; + if (util.isObject(item)) { + catchInstances[j++] = item; + } else { + return Promise.reject(new TypeError( + "tapCatch statement predicate: " + + "expecting an object but got " + util.classString(item) + )); + } + } + catchInstances.length = j; + var handler = arguments[i]; + return this._passThrough(catchFilter(catchInstances, handler, this), + 1, + undefined, + finallyHandler); + } + +}; + +return PassThroughHandlerContext; +}; diff --git a/express-server/node_modules/bluebird/js/release/generators.js b/express-server/node_modules/bluebird/js/release/generators.js new file mode 100644 index 00000000..500c280c --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/generators.js @@ -0,0 +1,223 @@ +"use strict"; +module.exports = function(Promise, + apiRejection, + INTERNAL, + tryConvertToPromise, + Proxyable, + debug) { +var errors = require("./errors"); +var TypeError = errors.TypeError; +var util = require("./util"); +var errorObj = util.errorObj; +var tryCatch = util.tryCatch; +var yieldHandlers = []; + +function promiseFromYieldHandler(value, yieldHandlers, traceParent) { + for (var i = 0; i < yieldHandlers.length; ++i) { + traceParent._pushContext(); + var result = tryCatch(yieldHandlers[i])(value); + traceParent._popContext(); + if (result === errorObj) { + traceParent._pushContext(); + var ret = Promise.reject(errorObj.e); + traceParent._popContext(); + return ret; + } + var maybePromise = tryConvertToPromise(result, traceParent); + if (maybePromise instanceof Promise) return maybePromise; + } + return null; +} + +function PromiseSpawn(generatorFunction, receiver, yieldHandler, stack) { + if (debug.cancellation()) { + var internal = new Promise(INTERNAL); + var _finallyPromise = this._finallyPromise = new Promise(INTERNAL); + this._promise = internal.lastly(function() { + return _finallyPromise; + }); + internal._captureStackTrace(); + internal._setOnCancel(this); + } else { + var promise = this._promise = new Promise(INTERNAL); + promise._captureStackTrace(); + } + this._stack = stack; + this._generatorFunction = generatorFunction; + this._receiver = receiver; + this._generator = undefined; + this._yieldHandlers = typeof yieldHandler === "function" + ? [yieldHandler].concat(yieldHandlers) + : yieldHandlers; + this._yieldedPromise = null; + this._cancellationPhase = false; +} +util.inherits(PromiseSpawn, Proxyable); + +PromiseSpawn.prototype._isResolved = function() { + return this._promise === null; +}; + +PromiseSpawn.prototype._cleanup = function() { + this._promise = this._generator = null; + if (debug.cancellation() && this._finallyPromise !== null) { + this._finallyPromise._fulfill(); + this._finallyPromise = null; + } +}; + +PromiseSpawn.prototype._promiseCancelled = function() { + if (this._isResolved()) return; + var implementsReturn = typeof this._generator["return"] !== "undefined"; + + var result; + if (!implementsReturn) { + var reason = new Promise.CancellationError( + "generator .return() sentinel"); + Promise.coroutine.returnSentinel = reason; + this._promise._attachExtraTrace(reason); + this._promise._pushContext(); + result = tryCatch(this._generator["throw"]).call(this._generator, + reason); + this._promise._popContext(); + } else { + this._promise._pushContext(); + result = tryCatch(this._generator["return"]).call(this._generator, + undefined); + this._promise._popContext(); + } + this._cancellationPhase = true; + this._yieldedPromise = null; + this._continue(result); +}; + +PromiseSpawn.prototype._promiseFulfilled = function(value) { + this._yieldedPromise = null; + this._promise._pushContext(); + var result = tryCatch(this._generator.next).call(this._generator, value); + this._promise._popContext(); + this._continue(result); +}; + +PromiseSpawn.prototype._promiseRejected = function(reason) { + this._yieldedPromise = null; + this._promise._attachExtraTrace(reason); + this._promise._pushContext(); + var result = tryCatch(this._generator["throw"]) + .call(this._generator, reason); + this._promise._popContext(); + this._continue(result); +}; + +PromiseSpawn.prototype._resultCancelled = function() { + if (this._yieldedPromise instanceof Promise) { + var promise = this._yieldedPromise; + this._yieldedPromise = null; + promise.cancel(); + } +}; + +PromiseSpawn.prototype.promise = function () { + return this._promise; +}; + +PromiseSpawn.prototype._run = function () { + this._generator = this._generatorFunction.call(this._receiver); + this._receiver = + this._generatorFunction = undefined; + this._promiseFulfilled(undefined); +}; + +PromiseSpawn.prototype._continue = function (result) { + var promise = this._promise; + if (result === errorObj) { + this._cleanup(); + if (this._cancellationPhase) { + return promise.cancel(); + } else { + return promise._rejectCallback(result.e, false); + } + } + + var value = result.value; + if (result.done === true) { + this._cleanup(); + if (this._cancellationPhase) { + return promise.cancel(); + } else { + return promise._resolveCallback(value); + } + } else { + var maybePromise = tryConvertToPromise(value, this._promise); + if (!(maybePromise instanceof Promise)) { + maybePromise = + promiseFromYieldHandler(maybePromise, + this._yieldHandlers, + this._promise); + if (maybePromise === null) { + this._promiseRejected( + new TypeError( + "A value %s was yielded that could not be treated as a promise\u000a\u000a See http://goo.gl/MqrFmX\u000a\u000a".replace("%s", String(value)) + + "From coroutine:\u000a" + + this._stack.split("\n").slice(1, -7).join("\n") + ) + ); + return; + } + } + maybePromise = maybePromise._target(); + var bitField = maybePromise._bitField; + ; + if (((bitField & 50397184) === 0)) { + this._yieldedPromise = maybePromise; + maybePromise._proxy(this, null); + } else if (((bitField & 33554432) !== 0)) { + Promise._async.invoke( + this._promiseFulfilled, this, maybePromise._value() + ); + } else if (((bitField & 16777216) !== 0)) { + Promise._async.invoke( + this._promiseRejected, this, maybePromise._reason() + ); + } else { + this._promiseCancelled(); + } + } +}; + +Promise.coroutine = function (generatorFunction, options) { + if (typeof generatorFunction !== "function") { + throw new TypeError("generatorFunction must be a function\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + var yieldHandler = Object(options).yieldHandler; + var PromiseSpawn$ = PromiseSpawn; + var stack = new Error().stack; + return function () { + var generator = generatorFunction.apply(this, arguments); + var spawn = new PromiseSpawn$(undefined, undefined, yieldHandler, + stack); + var ret = spawn.promise(); + spawn._generator = generator; + spawn._promiseFulfilled(undefined); + return ret; + }; +}; + +Promise.coroutine.addYieldHandler = function(fn) { + if (typeof fn !== "function") { + throw new TypeError("expecting a function but got " + util.classString(fn)); + } + yieldHandlers.push(fn); +}; + +Promise.spawn = function (generatorFunction) { + debug.deprecated("Promise.spawn()", "Promise.coroutine()"); + if (typeof generatorFunction !== "function") { + return apiRejection("generatorFunction must be a function\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + var spawn = new PromiseSpawn(generatorFunction, this); + var ret = spawn.promise(); + spawn._run(Promise.spawn); + return ret; +}; +}; diff --git a/express-server/node_modules/bluebird/js/release/join.js b/express-server/node_modules/bluebird/js/release/join.js new file mode 100644 index 00000000..4945e3f7 --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/join.js @@ -0,0 +1,168 @@ +"use strict"; +module.exports = +function(Promise, PromiseArray, tryConvertToPromise, INTERNAL, async, + getDomain) { +var util = require("./util"); +var canEvaluate = util.canEvaluate; +var tryCatch = util.tryCatch; +var errorObj = util.errorObj; +var reject; + +if (!false) { +if (canEvaluate) { + var thenCallback = function(i) { + return new Function("value", "holder", " \n\ + 'use strict'; \n\ + holder.pIndex = value; \n\ + holder.checkFulfillment(this); \n\ + ".replace(/Index/g, i)); + }; + + var promiseSetter = function(i) { + return new Function("promise", "holder", " \n\ + 'use strict'; \n\ + holder.pIndex = promise; \n\ + ".replace(/Index/g, i)); + }; + + var generateHolderClass = function(total) { + var props = new Array(total); + for (var i = 0; i < props.length; ++i) { + props[i] = "this.p" + (i+1); + } + var assignment = props.join(" = ") + " = null;"; + var cancellationCode= "var promise;\n" + props.map(function(prop) { + return " \n\ + promise = " + prop + "; \n\ + if (promise instanceof Promise) { \n\ + promise.cancel(); \n\ + } \n\ + "; + }).join("\n"); + var passedArguments = props.join(", "); + var name = "Holder$" + total; + + + var code = "return function(tryCatch, errorObj, Promise, async) { \n\ + 'use strict'; \n\ + function [TheName](fn) { \n\ + [TheProperties] \n\ + this.fn = fn; \n\ + this.asyncNeeded = true; \n\ + this.now = 0; \n\ + } \n\ + \n\ + [TheName].prototype._callFunction = function(promise) { \n\ + promise._pushContext(); \n\ + var ret = tryCatch(this.fn)([ThePassedArguments]); \n\ + promise._popContext(); \n\ + if (ret === errorObj) { \n\ + promise._rejectCallback(ret.e, false); \n\ + } else { \n\ + promise._resolveCallback(ret); \n\ + } \n\ + }; \n\ + \n\ + [TheName].prototype.checkFulfillment = function(promise) { \n\ + var now = ++this.now; \n\ + if (now === [TheTotal]) { \n\ + if (this.asyncNeeded) { \n\ + async.invoke(this._callFunction, this, promise); \n\ + } else { \n\ + this._callFunction(promise); \n\ + } \n\ + \n\ + } \n\ + }; \n\ + \n\ + [TheName].prototype._resultCancelled = function() { \n\ + [CancellationCode] \n\ + }; \n\ + \n\ + return [TheName]; \n\ + }(tryCatch, errorObj, Promise, async); \n\ + "; + + code = code.replace(/\[TheName\]/g, name) + .replace(/\[TheTotal\]/g, total) + .replace(/\[ThePassedArguments\]/g, passedArguments) + .replace(/\[TheProperties\]/g, assignment) + .replace(/\[CancellationCode\]/g, cancellationCode); + + return new Function("tryCatch", "errorObj", "Promise", "async", code) + (tryCatch, errorObj, Promise, async); + }; + + var holderClasses = []; + var thenCallbacks = []; + var promiseSetters = []; + + for (var i = 0; i < 8; ++i) { + holderClasses.push(generateHolderClass(i + 1)); + thenCallbacks.push(thenCallback(i + 1)); + promiseSetters.push(promiseSetter(i + 1)); + } + + reject = function (reason) { + this._reject(reason); + }; +}} + +Promise.join = function () { + var last = arguments.length - 1; + var fn; + if (last > 0 && typeof arguments[last] === "function") { + fn = arguments[last]; + if (!false) { + if (last <= 8 && canEvaluate) { + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + var HolderClass = holderClasses[last - 1]; + var holder = new HolderClass(fn); + var callbacks = thenCallbacks; + + for (var i = 0; i < last; ++i) { + var maybePromise = tryConvertToPromise(arguments[i], ret); + if (maybePromise instanceof Promise) { + maybePromise = maybePromise._target(); + var bitField = maybePromise._bitField; + ; + if (((bitField & 50397184) === 0)) { + maybePromise._then(callbacks[i], reject, + undefined, ret, holder); + promiseSetters[i](maybePromise, holder); + holder.asyncNeeded = false; + } else if (((bitField & 33554432) !== 0)) { + callbacks[i].call(ret, + maybePromise._value(), holder); + } else if (((bitField & 16777216) !== 0)) { + ret._reject(maybePromise._reason()); + } else { + ret._cancel(); + } + } else { + callbacks[i].call(ret, maybePromise, holder); + } + } + + if (!ret._isFateSealed()) { + if (holder.asyncNeeded) { + var domain = getDomain(); + if (domain !== null) { + holder.fn = util.domainBind(domain, holder.fn); + } + } + ret._setAsyncGuaranteed(); + ret._setOnCancel(holder); + } + return ret; + } + } + } + var $_len = arguments.length;var args = new Array($_len); for(var $_i = 0; $_i < $_len; ++$_i) {args[$_i] = arguments[$_i];}; + if (fn) args.pop(); + var ret = new PromiseArray(args).promise(); + return fn !== undefined ? ret.spread(fn) : ret; +}; + +}; diff --git a/express-server/node_modules/bluebird/js/release/map.js b/express-server/node_modules/bluebird/js/release/map.js new file mode 100644 index 00000000..976f15ef --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/map.js @@ -0,0 +1,168 @@ +"use strict"; +module.exports = function(Promise, + PromiseArray, + apiRejection, + tryConvertToPromise, + INTERNAL, + debug) { +var getDomain = Promise._getDomain; +var util = require("./util"); +var tryCatch = util.tryCatch; +var errorObj = util.errorObj; +var async = Promise._async; + +function MappingPromiseArray(promises, fn, limit, _filter) { + this.constructor$(promises); + this._promise._captureStackTrace(); + var domain = getDomain(); + this._callback = domain === null ? fn : util.domainBind(domain, fn); + this._preservedValues = _filter === INTERNAL + ? new Array(this.length()) + : null; + this._limit = limit; + this._inFlight = 0; + this._queue = []; + async.invoke(this._asyncInit, this, undefined); +} +util.inherits(MappingPromiseArray, PromiseArray); + +MappingPromiseArray.prototype._asyncInit = function() { + this._init$(undefined, -2); +}; + +MappingPromiseArray.prototype._init = function () {}; + +MappingPromiseArray.prototype._promiseFulfilled = function (value, index) { + var values = this._values; + var length = this.length(); + var preservedValues = this._preservedValues; + var limit = this._limit; + + if (index < 0) { + index = (index * -1) - 1; + values[index] = value; + if (limit >= 1) { + this._inFlight--; + this._drainQueue(); + if (this._isResolved()) return true; + } + } else { + if (limit >= 1 && this._inFlight >= limit) { + values[index] = value; + this._queue.push(index); + return false; + } + if (preservedValues !== null) preservedValues[index] = value; + + var promise = this._promise; + var callback = this._callback; + var receiver = promise._boundValue(); + promise._pushContext(); + var ret = tryCatch(callback).call(receiver, value, index, length); + var promiseCreated = promise._popContext(); + debug.checkForgottenReturns( + ret, + promiseCreated, + preservedValues !== null ? "Promise.filter" : "Promise.map", + promise + ); + if (ret === errorObj) { + this._reject(ret.e); + return true; + } + + var maybePromise = tryConvertToPromise(ret, this._promise); + if (maybePromise instanceof Promise) { + maybePromise = maybePromise._target(); + var bitField = maybePromise._bitField; + ; + if (((bitField & 50397184) === 0)) { + if (limit >= 1) this._inFlight++; + values[index] = maybePromise; + maybePromise._proxy(this, (index + 1) * -1); + return false; + } else if (((bitField & 33554432) !== 0)) { + ret = maybePromise._value(); + } else if (((bitField & 16777216) !== 0)) { + this._reject(maybePromise._reason()); + return true; + } else { + this._cancel(); + return true; + } + } + values[index] = ret; + } + var totalResolved = ++this._totalResolved; + if (totalResolved >= length) { + if (preservedValues !== null) { + this._filter(values, preservedValues); + } else { + this._resolve(values); + } + return true; + } + return false; +}; + +MappingPromiseArray.prototype._drainQueue = function () { + var queue = this._queue; + var limit = this._limit; + var values = this._values; + while (queue.length > 0 && this._inFlight < limit) { + if (this._isResolved()) return; + var index = queue.pop(); + this._promiseFulfilled(values[index], index); + } +}; + +MappingPromiseArray.prototype._filter = function (booleans, values) { + var len = values.length; + var ret = new Array(len); + var j = 0; + for (var i = 0; i < len; ++i) { + if (booleans[i]) ret[j++] = values[i]; + } + ret.length = j; + this._resolve(ret); +}; + +MappingPromiseArray.prototype.preservedValues = function () { + return this._preservedValues; +}; + +function map(promises, fn, options, _filter) { + if (typeof fn !== "function") { + return apiRejection("expecting a function but got " + util.classString(fn)); + } + + var limit = 0; + if (options !== undefined) { + if (typeof options === "object" && options !== null) { + if (typeof options.concurrency !== "number") { + return Promise.reject( + new TypeError("'concurrency' must be a number but it is " + + util.classString(options.concurrency))); + } + limit = options.concurrency; + } else { + return Promise.reject(new TypeError( + "options argument must be an object but it is " + + util.classString(options))); + } + } + limit = typeof limit === "number" && + isFinite(limit) && limit >= 1 ? limit : 0; + return new MappingPromiseArray(promises, fn, limit, _filter).promise(); +} + +Promise.prototype.map = function (fn, options) { + return map(this, fn, options, null); +}; + +Promise.map = function (promises, fn, options, _filter) { + return map(promises, fn, options, _filter); +}; + + +}; diff --git a/express-server/node_modules/bluebird/js/release/method.js b/express-server/node_modules/bluebird/js/release/method.js new file mode 100644 index 00000000..ce9e4db7 --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/method.js @@ -0,0 +1,55 @@ +"use strict"; +module.exports = +function(Promise, INTERNAL, tryConvertToPromise, apiRejection, debug) { +var util = require("./util"); +var tryCatch = util.tryCatch; + +Promise.method = function (fn) { + if (typeof fn !== "function") { + throw new Promise.TypeError("expecting a function but got " + util.classString(fn)); + } + return function () { + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + ret._pushContext(); + var value = tryCatch(fn).apply(this, arguments); + var promiseCreated = ret._popContext(); + debug.checkForgottenReturns( + value, promiseCreated, "Promise.method", ret); + ret._resolveFromSyncValue(value); + return ret; + }; +}; + +Promise.attempt = Promise["try"] = function (fn) { + if (typeof fn !== "function") { + return apiRejection("expecting a function but got " + util.classString(fn)); + } + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + ret._pushContext(); + var value; + if (arguments.length > 1) { + debug.deprecated("calling Promise.try with more than 1 argument"); + var arg = arguments[1]; + var ctx = arguments[2]; + value = util.isArray(arg) ? tryCatch(fn).apply(ctx, arg) + : tryCatch(fn).call(ctx, arg); + } else { + value = tryCatch(fn)(); + } + var promiseCreated = ret._popContext(); + debug.checkForgottenReturns( + value, promiseCreated, "Promise.try", ret); + ret._resolveFromSyncValue(value); + return ret; +}; + +Promise.prototype._resolveFromSyncValue = function (value) { + if (value === util.errorObj) { + this._rejectCallback(value.e, false); + } else { + this._resolveCallback(value, true); + } +}; +}; diff --git a/express-server/node_modules/bluebird/js/release/nodeback.js b/express-server/node_modules/bluebird/js/release/nodeback.js new file mode 100644 index 00000000..71e69ebd --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/nodeback.js @@ -0,0 +1,51 @@ +"use strict"; +var util = require("./util"); +var maybeWrapAsError = util.maybeWrapAsError; +var errors = require("./errors"); +var OperationalError = errors.OperationalError; +var es5 = require("./es5"); + +function isUntypedError(obj) { + return obj instanceof Error && + es5.getPrototypeOf(obj) === Error.prototype; +} + +var rErrorKey = /^(?:name|message|stack|cause)$/; +function wrapAsOperationalError(obj) { + var ret; + if (isUntypedError(obj)) { + ret = new OperationalError(obj); + ret.name = obj.name; + ret.message = obj.message; + ret.stack = obj.stack; + var keys = es5.keys(obj); + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (!rErrorKey.test(key)) { + ret[key] = obj[key]; + } + } + return ret; + } + util.markAsOriginatingFromRejection(obj); + return obj; +} + +function nodebackForPromise(promise, multiArgs) { + return function(err, value) { + if (promise === null) return; + if (err) { + var wrapped = wrapAsOperationalError(maybeWrapAsError(err)); + promise._attachExtraTrace(wrapped); + promise._reject(wrapped); + } else if (!multiArgs) { + promise._fulfill(value); + } else { + var $_len = arguments.length;var args = new Array(Math.max($_len - 1, 0)); for(var $_i = 1; $_i < $_len; ++$_i) {args[$_i - 1] = arguments[$_i];}; + promise._fulfill(args); + } + promise = null; + }; +} + +module.exports = nodebackForPromise; diff --git a/express-server/node_modules/bluebird/js/release/nodeify.js b/express-server/node_modules/bluebird/js/release/nodeify.js new file mode 100644 index 00000000..ce2b1900 --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/nodeify.js @@ -0,0 +1,58 @@ +"use strict"; +module.exports = function(Promise) { +var util = require("./util"); +var async = Promise._async; +var tryCatch = util.tryCatch; +var errorObj = util.errorObj; + +function spreadAdapter(val, nodeback) { + var promise = this; + if (!util.isArray(val)) return successAdapter.call(promise, val, nodeback); + var ret = + tryCatch(nodeback).apply(promise._boundValue(), [null].concat(val)); + if (ret === errorObj) { + async.throwLater(ret.e); + } +} + +function successAdapter(val, nodeback) { + var promise = this; + var receiver = promise._boundValue(); + var ret = val === undefined + ? tryCatch(nodeback).call(receiver, null) + : tryCatch(nodeback).call(receiver, null, val); + if (ret === errorObj) { + async.throwLater(ret.e); + } +} +function errorAdapter(reason, nodeback) { + var promise = this; + if (!reason) { + var newReason = new Error(reason + ""); + newReason.cause = reason; + reason = newReason; + } + var ret = tryCatch(nodeback).call(promise._boundValue(), reason); + if (ret === errorObj) { + async.throwLater(ret.e); + } +} + +Promise.prototype.asCallback = Promise.prototype.nodeify = function (nodeback, + options) { + if (typeof nodeback == "function") { + var adapter = successAdapter; + if (options !== undefined && Object(options).spread) { + adapter = spreadAdapter; + } + this._then( + adapter, + errorAdapter, + undefined, + this, + nodeback + ); + } + return this; +}; +}; diff --git a/express-server/node_modules/bluebird/js/release/promise.js b/express-server/node_modules/bluebird/js/release/promise.js new file mode 100644 index 00000000..f28d2f01 --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/promise.js @@ -0,0 +1,776 @@ +"use strict"; +module.exports = function() { +var makeSelfResolutionError = function () { + return new TypeError("circular promise resolution chain\u000a\u000a See http://goo.gl/MqrFmX\u000a"); +}; +var reflectHandler = function() { + return new Promise.PromiseInspection(this._target()); +}; +var apiRejection = function(msg) { + return Promise.reject(new TypeError(msg)); +}; +function Proxyable() {} +var UNDEFINED_BINDING = {}; +var util = require("./util"); + +var getDomain; +if (util.isNode) { + getDomain = function() { + var ret = process.domain; + if (ret === undefined) ret = null; + return ret; + }; +} else { + getDomain = function() { + return null; + }; +} +util.notEnumerableProp(Promise, "_getDomain", getDomain); + +var es5 = require("./es5"); +var Async = require("./async"); +var async = new Async(); +es5.defineProperty(Promise, "_async", {value: async}); +var errors = require("./errors"); +var TypeError = Promise.TypeError = errors.TypeError; +Promise.RangeError = errors.RangeError; +var CancellationError = Promise.CancellationError = errors.CancellationError; +Promise.TimeoutError = errors.TimeoutError; +Promise.OperationalError = errors.OperationalError; +Promise.RejectionError = errors.OperationalError; +Promise.AggregateError = errors.AggregateError; +var INTERNAL = function(){}; +var APPLY = {}; +var NEXT_FILTER = {}; +var tryConvertToPromise = require("./thenables")(Promise, INTERNAL); +var PromiseArray = + require("./promise_array")(Promise, INTERNAL, + tryConvertToPromise, apiRejection, Proxyable); +var Context = require("./context")(Promise); + /*jshint unused:false*/ +var createContext = Context.create; +var debug = require("./debuggability")(Promise, Context); +var CapturedTrace = debug.CapturedTrace; +var PassThroughHandlerContext = + require("./finally")(Promise, tryConvertToPromise, NEXT_FILTER); +var catchFilter = require("./catch_filter")(NEXT_FILTER); +var nodebackForPromise = require("./nodeback"); +var errorObj = util.errorObj; +var tryCatch = util.tryCatch; +function check(self, executor) { + if (self == null || self.constructor !== Promise) { + throw new TypeError("the promise constructor cannot be invoked directly\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + if (typeof executor !== "function") { + throw new TypeError("expecting a function but got " + util.classString(executor)); + } + +} + +function Promise(executor) { + if (executor !== INTERNAL) { + check(this, executor); + } + this._bitField = 0; + this._fulfillmentHandler0 = undefined; + this._rejectionHandler0 = undefined; + this._promise0 = undefined; + this._receiver0 = undefined; + this._resolveFromExecutor(executor); + this._promiseCreated(); + this._fireEvent("promiseCreated", this); +} + +Promise.prototype.toString = function () { + return "[object Promise]"; +}; + +Promise.prototype.caught = Promise.prototype["catch"] = function (fn) { + var len = arguments.length; + if (len > 1) { + var catchInstances = new Array(len - 1), + j = 0, i; + for (i = 0; i < len - 1; ++i) { + var item = arguments[i]; + if (util.isObject(item)) { + catchInstances[j++] = item; + } else { + return apiRejection("Catch statement predicate: " + + "expecting an object but got " + util.classString(item)); + } + } + catchInstances.length = j; + fn = arguments[i]; + return this.then(undefined, catchFilter(catchInstances, fn, this)); + } + return this.then(undefined, fn); +}; + +Promise.prototype.reflect = function () { + return this._then(reflectHandler, + reflectHandler, undefined, this, undefined); +}; + +Promise.prototype.then = function (didFulfill, didReject) { + if (debug.warnings() && arguments.length > 0 && + typeof didFulfill !== "function" && + typeof didReject !== "function") { + var msg = ".then() only accepts functions but was passed: " + + util.classString(didFulfill); + if (arguments.length > 1) { + msg += ", " + util.classString(didReject); + } + this._warn(msg); + } + return this._then(didFulfill, didReject, undefined, undefined, undefined); +}; + +Promise.prototype.done = function (didFulfill, didReject) { + var promise = + this._then(didFulfill, didReject, undefined, undefined, undefined); + promise._setIsFinal(); +}; + +Promise.prototype.spread = function (fn) { + if (typeof fn !== "function") { + return apiRejection("expecting a function but got " + util.classString(fn)); + } + return this.all()._then(fn, undefined, undefined, APPLY, undefined); +}; + +Promise.prototype.toJSON = function () { + var ret = { + isFulfilled: false, + isRejected: false, + fulfillmentValue: undefined, + rejectionReason: undefined + }; + if (this.isFulfilled()) { + ret.fulfillmentValue = this.value(); + ret.isFulfilled = true; + } else if (this.isRejected()) { + ret.rejectionReason = this.reason(); + ret.isRejected = true; + } + return ret; +}; + +Promise.prototype.all = function () { + if (arguments.length > 0) { + this._warn(".all() was passed arguments but it does not take any"); + } + return new PromiseArray(this).promise(); +}; + +Promise.prototype.error = function (fn) { + return this.caught(util.originatesFromRejection, fn); +}; + +Promise.getNewLibraryCopy = module.exports; + +Promise.is = function (val) { + return val instanceof Promise; +}; + +Promise.fromNode = Promise.fromCallback = function(fn) { + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + var multiArgs = arguments.length > 1 ? !!Object(arguments[1]).multiArgs + : false; + var result = tryCatch(fn)(nodebackForPromise(ret, multiArgs)); + if (result === errorObj) { + ret._rejectCallback(result.e, true); + } + if (!ret._isFateSealed()) ret._setAsyncGuaranteed(); + return ret; +}; + +Promise.all = function (promises) { + return new PromiseArray(promises).promise(); +}; + +Promise.cast = function (obj) { + var ret = tryConvertToPromise(obj); + if (!(ret instanceof Promise)) { + ret = new Promise(INTERNAL); + ret._captureStackTrace(); + ret._setFulfilled(); + ret._rejectionHandler0 = obj; + } + return ret; +}; + +Promise.resolve = Promise.fulfilled = Promise.cast; + +Promise.reject = Promise.rejected = function (reason) { + var ret = new Promise(INTERNAL); + ret._captureStackTrace(); + ret._rejectCallback(reason, true); + return ret; +}; + +Promise.setScheduler = function(fn) { + if (typeof fn !== "function") { + throw new TypeError("expecting a function but got " + util.classString(fn)); + } + return async.setScheduler(fn); +}; + +Promise.prototype._then = function ( + didFulfill, + didReject, + _, receiver, + internalData +) { + var haveInternalData = internalData !== undefined; + var promise = haveInternalData ? internalData : new Promise(INTERNAL); + var target = this._target(); + var bitField = target._bitField; + + if (!haveInternalData) { + promise._propagateFrom(this, 3); + promise._captureStackTrace(); + if (receiver === undefined && + ((this._bitField & 2097152) !== 0)) { + if (!((bitField & 50397184) === 0)) { + receiver = this._boundValue(); + } else { + receiver = target === this ? undefined : this._boundTo; + } + } + this._fireEvent("promiseChained", this, promise); + } + + var domain = getDomain(); + if (!((bitField & 50397184) === 0)) { + var handler, value, settler = target._settlePromiseCtx; + if (((bitField & 33554432) !== 0)) { + value = target._rejectionHandler0; + handler = didFulfill; + } else if (((bitField & 16777216) !== 0)) { + value = target._fulfillmentHandler0; + handler = didReject; + target._unsetRejectionIsUnhandled(); + } else { + settler = target._settlePromiseLateCancellationObserver; + value = new CancellationError("late cancellation observer"); + target._attachExtraTrace(value); + handler = didReject; + } + + async.invoke(settler, target, { + handler: domain === null ? handler + : (typeof handler === "function" && + util.domainBind(domain, handler)), + promise: promise, + receiver: receiver, + value: value + }); + } else { + target._addCallbacks(didFulfill, didReject, promise, receiver, domain); + } + + return promise; +}; + +Promise.prototype._length = function () { + return this._bitField & 65535; +}; + +Promise.prototype._isFateSealed = function () { + return (this._bitField & 117506048) !== 0; +}; + +Promise.prototype._isFollowing = function () { + return (this._bitField & 67108864) === 67108864; +}; + +Promise.prototype._setLength = function (len) { + this._bitField = (this._bitField & -65536) | + (len & 65535); +}; + +Promise.prototype._setFulfilled = function () { + this._bitField = this._bitField | 33554432; + this._fireEvent("promiseFulfilled", this); +}; + +Promise.prototype._setRejected = function () { + this._bitField = this._bitField | 16777216; + this._fireEvent("promiseRejected", this); +}; + +Promise.prototype._setFollowing = function () { + this._bitField = this._bitField | 67108864; + this._fireEvent("promiseResolved", this); +}; + +Promise.prototype._setIsFinal = function () { + this._bitField = this._bitField | 4194304; +}; + +Promise.prototype._isFinal = function () { + return (this._bitField & 4194304) > 0; +}; + +Promise.prototype._unsetCancelled = function() { + this._bitField = this._bitField & (~65536); +}; + +Promise.prototype._setCancelled = function() { + this._bitField = this._bitField | 65536; + this._fireEvent("promiseCancelled", this); +}; + +Promise.prototype._setWillBeCancelled = function() { + this._bitField = this._bitField | 8388608; +}; + +Promise.prototype._setAsyncGuaranteed = function() { + if (async.hasCustomScheduler()) return; + this._bitField = this._bitField | 134217728; +}; + +Promise.prototype._receiverAt = function (index) { + var ret = index === 0 ? this._receiver0 : this[ + index * 4 - 4 + 3]; + if (ret === UNDEFINED_BINDING) { + return undefined; + } else if (ret === undefined && this._isBound()) { + return this._boundValue(); + } + return ret; +}; + +Promise.prototype._promiseAt = function (index) { + return this[ + index * 4 - 4 + 2]; +}; + +Promise.prototype._fulfillmentHandlerAt = function (index) { + return this[ + index * 4 - 4 + 0]; +}; + +Promise.prototype._rejectionHandlerAt = function (index) { + return this[ + index * 4 - 4 + 1]; +}; + +Promise.prototype._boundValue = function() {}; + +Promise.prototype._migrateCallback0 = function (follower) { + var bitField = follower._bitField; + var fulfill = follower._fulfillmentHandler0; + var reject = follower._rejectionHandler0; + var promise = follower._promise0; + var receiver = follower._receiverAt(0); + if (receiver === undefined) receiver = UNDEFINED_BINDING; + this._addCallbacks(fulfill, reject, promise, receiver, null); +}; + +Promise.prototype._migrateCallbackAt = function (follower, index) { + var fulfill = follower._fulfillmentHandlerAt(index); + var reject = follower._rejectionHandlerAt(index); + var promise = follower._promiseAt(index); + var receiver = follower._receiverAt(index); + if (receiver === undefined) receiver = UNDEFINED_BINDING; + this._addCallbacks(fulfill, reject, promise, receiver, null); +}; + +Promise.prototype._addCallbacks = function ( + fulfill, + reject, + promise, + receiver, + domain +) { + var index = this._length(); + + if (index >= 65535 - 4) { + index = 0; + this._setLength(0); + } + + if (index === 0) { + this._promise0 = promise; + this._receiver0 = receiver; + if (typeof fulfill === "function") { + this._fulfillmentHandler0 = + domain === null ? fulfill : util.domainBind(domain, fulfill); + } + if (typeof reject === "function") { + this._rejectionHandler0 = + domain === null ? reject : util.domainBind(domain, reject); + } + } else { + var base = index * 4 - 4; + this[base + 2] = promise; + this[base + 3] = receiver; + if (typeof fulfill === "function") { + this[base + 0] = + domain === null ? fulfill : util.domainBind(domain, fulfill); + } + if (typeof reject === "function") { + this[base + 1] = + domain === null ? reject : util.domainBind(domain, reject); + } + } + this._setLength(index + 1); + return index; +}; + +Promise.prototype._proxy = function (proxyable, arg) { + this._addCallbacks(undefined, undefined, arg, proxyable, null); +}; + +Promise.prototype._resolveCallback = function(value, shouldBind) { + if (((this._bitField & 117506048) !== 0)) return; + if (value === this) + return this._rejectCallback(makeSelfResolutionError(), false); + var maybePromise = tryConvertToPromise(value, this); + if (!(maybePromise instanceof Promise)) return this._fulfill(value); + + if (shouldBind) this._propagateFrom(maybePromise, 2); + + var promise = maybePromise._target(); + + if (promise === this) { + this._reject(makeSelfResolutionError()); + return; + } + + var bitField = promise._bitField; + if (((bitField & 50397184) === 0)) { + var len = this._length(); + if (len > 0) promise._migrateCallback0(this); + for (var i = 1; i < len; ++i) { + promise._migrateCallbackAt(this, i); + } + this._setFollowing(); + this._setLength(0); + this._setFollowee(promise); + } else if (((bitField & 33554432) !== 0)) { + this._fulfill(promise._value()); + } else if (((bitField & 16777216) !== 0)) { + this._reject(promise._reason()); + } else { + var reason = new CancellationError("late cancellation observer"); + promise._attachExtraTrace(reason); + this._reject(reason); + } +}; + +Promise.prototype._rejectCallback = +function(reason, synchronous, ignoreNonErrorWarnings) { + var trace = util.ensureErrorObject(reason); + var hasStack = trace === reason; + if (!hasStack && !ignoreNonErrorWarnings && debug.warnings()) { + var message = "a promise was rejected with a non-error: " + + util.classString(reason); + this._warn(message, true); + } + this._attachExtraTrace(trace, synchronous ? hasStack : false); + this._reject(reason); +}; + +Promise.prototype._resolveFromExecutor = function (executor) { + if (executor === INTERNAL) return; + var promise = this; + this._captureStackTrace(); + this._pushContext(); + var synchronous = true; + var r = this._execute(executor, function(value) { + promise._resolveCallback(value); + }, function (reason) { + promise._rejectCallback(reason, synchronous); + }); + synchronous = false; + this._popContext(); + + if (r !== undefined) { + promise._rejectCallback(r, true); + } +}; + +Promise.prototype._settlePromiseFromHandler = function ( + handler, receiver, value, promise +) { + var bitField = promise._bitField; + if (((bitField & 65536) !== 0)) return; + promise._pushContext(); + var x; + if (receiver === APPLY) { + if (!value || typeof value.length !== "number") { + x = errorObj; + x.e = new TypeError("cannot .spread() a non-array: " + + util.classString(value)); + } else { + x = tryCatch(handler).apply(this._boundValue(), value); + } + } else { + x = tryCatch(handler).call(receiver, value); + } + var promiseCreated = promise._popContext(); + bitField = promise._bitField; + if (((bitField & 65536) !== 0)) return; + + if (x === NEXT_FILTER) { + promise._reject(value); + } else if (x === errorObj) { + promise._rejectCallback(x.e, false); + } else { + debug.checkForgottenReturns(x, promiseCreated, "", promise, this); + promise._resolveCallback(x); + } +}; + +Promise.prototype._target = function() { + var ret = this; + while (ret._isFollowing()) ret = ret._followee(); + return ret; +}; + +Promise.prototype._followee = function() { + return this._rejectionHandler0; +}; + +Promise.prototype._setFollowee = function(promise) { + this._rejectionHandler0 = promise; +}; + +Promise.prototype._settlePromise = function(promise, handler, receiver, value) { + var isPromise = promise instanceof Promise; + var bitField = this._bitField; + var asyncGuaranteed = ((bitField & 134217728) !== 0); + if (((bitField & 65536) !== 0)) { + if (isPromise) promise._invokeInternalOnCancel(); + + if (receiver instanceof PassThroughHandlerContext && + receiver.isFinallyHandler()) { + receiver.cancelPromise = promise; + if (tryCatch(handler).call(receiver, value) === errorObj) { + promise._reject(errorObj.e); + } + } else if (handler === reflectHandler) { + promise._fulfill(reflectHandler.call(receiver)); + } else if (receiver instanceof Proxyable) { + receiver._promiseCancelled(promise); + } else if (isPromise || promise instanceof PromiseArray) { + promise._cancel(); + } else { + receiver.cancel(); + } + } else if (typeof handler === "function") { + if (!isPromise) { + handler.call(receiver, value, promise); + } else { + if (asyncGuaranteed) promise._setAsyncGuaranteed(); + this._settlePromiseFromHandler(handler, receiver, value, promise); + } + } else if (receiver instanceof Proxyable) { + if (!receiver._isResolved()) { + if (((bitField & 33554432) !== 0)) { + receiver._promiseFulfilled(value, promise); + } else { + receiver._promiseRejected(value, promise); + } + } + } else if (isPromise) { + if (asyncGuaranteed) promise._setAsyncGuaranteed(); + if (((bitField & 33554432) !== 0)) { + promise._fulfill(value); + } else { + promise._reject(value); + } + } +}; + +Promise.prototype._settlePromiseLateCancellationObserver = function(ctx) { + var handler = ctx.handler; + var promise = ctx.promise; + var receiver = ctx.receiver; + var value = ctx.value; + if (typeof handler === "function") { + if (!(promise instanceof Promise)) { + handler.call(receiver, value, promise); + } else { + this._settlePromiseFromHandler(handler, receiver, value, promise); + } + } else if (promise instanceof Promise) { + promise._reject(value); + } +}; + +Promise.prototype._settlePromiseCtx = function(ctx) { + this._settlePromise(ctx.promise, ctx.handler, ctx.receiver, ctx.value); +}; + +Promise.prototype._settlePromise0 = function(handler, value, bitField) { + var promise = this._promise0; + var receiver = this._receiverAt(0); + this._promise0 = undefined; + this._receiver0 = undefined; + this._settlePromise(promise, handler, receiver, value); +}; + +Promise.prototype._clearCallbackDataAtIndex = function(index) { + var base = index * 4 - 4; + this[base + 2] = + this[base + 3] = + this[base + 0] = + this[base + 1] = undefined; +}; + +Promise.prototype._fulfill = function (value) { + var bitField = this._bitField; + if (((bitField & 117506048) >>> 16)) return; + if (value === this) { + var err = makeSelfResolutionError(); + this._attachExtraTrace(err); + return this._reject(err); + } + this._setFulfilled(); + this._rejectionHandler0 = value; + + if ((bitField & 65535) > 0) { + if (((bitField & 134217728) !== 0)) { + this._settlePromises(); + } else { + async.settlePromises(this); + } + this._dereferenceTrace(); + } +}; + +Promise.prototype._reject = function (reason) { + var bitField = this._bitField; + if (((bitField & 117506048) >>> 16)) return; + this._setRejected(); + this._fulfillmentHandler0 = reason; + + if (this._isFinal()) { + return async.fatalError(reason, util.isNode); + } + + if ((bitField & 65535) > 0) { + async.settlePromises(this); + } else { + this._ensurePossibleRejectionHandled(); + } +}; + +Promise.prototype._fulfillPromises = function (len, value) { + for (var i = 1; i < len; i++) { + var handler = this._fulfillmentHandlerAt(i); + var promise = this._promiseAt(i); + var receiver = this._receiverAt(i); + this._clearCallbackDataAtIndex(i); + this._settlePromise(promise, handler, receiver, value); + } +}; + +Promise.prototype._rejectPromises = function (len, reason) { + for (var i = 1; i < len; i++) { + var handler = this._rejectionHandlerAt(i); + var promise = this._promiseAt(i); + var receiver = this._receiverAt(i); + this._clearCallbackDataAtIndex(i); + this._settlePromise(promise, handler, receiver, reason); + } +}; + +Promise.prototype._settlePromises = function () { + var bitField = this._bitField; + var len = (bitField & 65535); + + if (len > 0) { + if (((bitField & 16842752) !== 0)) { + var reason = this._fulfillmentHandler0; + this._settlePromise0(this._rejectionHandler0, reason, bitField); + this._rejectPromises(len, reason); + } else { + var value = this._rejectionHandler0; + this._settlePromise0(this._fulfillmentHandler0, value, bitField); + this._fulfillPromises(len, value); + } + this._setLength(0); + } + this._clearCancellationData(); +}; + +Promise.prototype._settledValue = function() { + var bitField = this._bitField; + if (((bitField & 33554432) !== 0)) { + return this._rejectionHandler0; + } else if (((bitField & 16777216) !== 0)) { + return this._fulfillmentHandler0; + } +}; + +function deferResolve(v) {this.promise._resolveCallback(v);} +function deferReject(v) {this.promise._rejectCallback(v, false);} + +Promise.defer = Promise.pending = function() { + debug.deprecated("Promise.defer", "new Promise"); + var promise = new Promise(INTERNAL); + return { + promise: promise, + resolve: deferResolve, + reject: deferReject + }; +}; + +util.notEnumerableProp(Promise, + "_makeSelfResolutionError", + makeSelfResolutionError); + +require("./method")(Promise, INTERNAL, tryConvertToPromise, apiRejection, + debug); +require("./bind")(Promise, INTERNAL, tryConvertToPromise, debug); +require("./cancel")(Promise, PromiseArray, apiRejection, debug); +require("./direct_resolve")(Promise); +require("./synchronous_inspection")(Promise); +require("./join")( + Promise, PromiseArray, tryConvertToPromise, INTERNAL, async, getDomain); +Promise.Promise = Promise; +Promise.version = "3.5.3"; +require('./map.js')(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL, debug); +require('./call_get.js')(Promise); +require('./using.js')(Promise, apiRejection, tryConvertToPromise, createContext, INTERNAL, debug); +require('./timers.js')(Promise, INTERNAL, debug); +require('./generators.js')(Promise, apiRejection, INTERNAL, tryConvertToPromise, Proxyable, debug); +require('./nodeify.js')(Promise); +require('./promisify.js')(Promise, INTERNAL); +require('./props.js')(Promise, PromiseArray, tryConvertToPromise, apiRejection); +require('./race.js')(Promise, INTERNAL, tryConvertToPromise, apiRejection); +require('./reduce.js')(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL, debug); +require('./settle.js')(Promise, PromiseArray, debug); +require('./some.js')(Promise, PromiseArray, apiRejection); +require('./filter.js')(Promise, INTERNAL); +require('./each.js')(Promise, INTERNAL); +require('./any.js')(Promise); + + util.toFastProperties(Promise); + util.toFastProperties(Promise.prototype); + function fillTypes(value) { + var p = new Promise(INTERNAL); + p._fulfillmentHandler0 = value; + p._rejectionHandler0 = value; + p._promise0 = value; + p._receiver0 = value; + } + // Complete slack tracking, opt out of field-type tracking and + // stabilize map + fillTypes({a: 1}); + fillTypes({b: 2}); + fillTypes({c: 3}); + fillTypes(1); + fillTypes(function(){}); + fillTypes(undefined); + fillTypes(false); + fillTypes(new Promise(INTERNAL)); + debug.setBounds(Async.firstLineError, util.lastLineError); + return Promise; + +}; diff --git a/express-server/node_modules/bluebird/js/release/promise_array.js b/express-server/node_modules/bluebird/js/release/promise_array.js new file mode 100644 index 00000000..0fb303eb --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/promise_array.js @@ -0,0 +1,185 @@ +"use strict"; +module.exports = function(Promise, INTERNAL, tryConvertToPromise, + apiRejection, Proxyable) { +var util = require("./util"); +var isArray = util.isArray; + +function toResolutionValue(val) { + switch(val) { + case -2: return []; + case -3: return {}; + case -6: return new Map(); + } +} + +function PromiseArray(values) { + var promise = this._promise = new Promise(INTERNAL); + if (values instanceof Promise) { + promise._propagateFrom(values, 3); + } + promise._setOnCancel(this); + this._values = values; + this._length = 0; + this._totalResolved = 0; + this._init(undefined, -2); +} +util.inherits(PromiseArray, Proxyable); + +PromiseArray.prototype.length = function () { + return this._length; +}; + +PromiseArray.prototype.promise = function () { + return this._promise; +}; + +PromiseArray.prototype._init = function init(_, resolveValueIfEmpty) { + var values = tryConvertToPromise(this._values, this._promise); + if (values instanceof Promise) { + values = values._target(); + var bitField = values._bitField; + ; + this._values = values; + + if (((bitField & 50397184) === 0)) { + this._promise._setAsyncGuaranteed(); + return values._then( + init, + this._reject, + undefined, + this, + resolveValueIfEmpty + ); + } else if (((bitField & 33554432) !== 0)) { + values = values._value(); + } else if (((bitField & 16777216) !== 0)) { + return this._reject(values._reason()); + } else { + return this._cancel(); + } + } + values = util.asArray(values); + if (values === null) { + var err = apiRejection( + "expecting an array or an iterable object but got " + util.classString(values)).reason(); + this._promise._rejectCallback(err, false); + return; + } + + if (values.length === 0) { + if (resolveValueIfEmpty === -5) { + this._resolveEmptyArray(); + } + else { + this._resolve(toResolutionValue(resolveValueIfEmpty)); + } + return; + } + this._iterate(values); +}; + +PromiseArray.prototype._iterate = function(values) { + var len = this.getActualLength(values.length); + this._length = len; + this._values = this.shouldCopyValues() ? new Array(len) : this._values; + var result = this._promise; + var isResolved = false; + var bitField = null; + for (var i = 0; i < len; ++i) { + var maybePromise = tryConvertToPromise(values[i], result); + + if (maybePromise instanceof Promise) { + maybePromise = maybePromise._target(); + bitField = maybePromise._bitField; + } else { + bitField = null; + } + + if (isResolved) { + if (bitField !== null) { + maybePromise.suppressUnhandledRejections(); + } + } else if (bitField !== null) { + if (((bitField & 50397184) === 0)) { + maybePromise._proxy(this, i); + this._values[i] = maybePromise; + } else if (((bitField & 33554432) !== 0)) { + isResolved = this._promiseFulfilled(maybePromise._value(), i); + } else if (((bitField & 16777216) !== 0)) { + isResolved = this._promiseRejected(maybePromise._reason(), i); + } else { + isResolved = this._promiseCancelled(i); + } + } else { + isResolved = this._promiseFulfilled(maybePromise, i); + } + } + if (!isResolved) result._setAsyncGuaranteed(); +}; + +PromiseArray.prototype._isResolved = function () { + return this._values === null; +}; + +PromiseArray.prototype._resolve = function (value) { + this._values = null; + this._promise._fulfill(value); +}; + +PromiseArray.prototype._cancel = function() { + if (this._isResolved() || !this._promise._isCancellable()) return; + this._values = null; + this._promise._cancel(); +}; + +PromiseArray.prototype._reject = function (reason) { + this._values = null; + this._promise._rejectCallback(reason, false); +}; + +PromiseArray.prototype._promiseFulfilled = function (value, index) { + this._values[index] = value; + var totalResolved = ++this._totalResolved; + if (totalResolved >= this._length) { + this._resolve(this._values); + return true; + } + return false; +}; + +PromiseArray.prototype._promiseCancelled = function() { + this._cancel(); + return true; +}; + +PromiseArray.prototype._promiseRejected = function (reason) { + this._totalResolved++; + this._reject(reason); + return true; +}; + +PromiseArray.prototype._resultCancelled = function() { + if (this._isResolved()) return; + var values = this._values; + this._cancel(); + if (values instanceof Promise) { + values.cancel(); + } else { + for (var i = 0; i < values.length; ++i) { + if (values[i] instanceof Promise) { + values[i].cancel(); + } + } + } +}; + +PromiseArray.prototype.shouldCopyValues = function () { + return true; +}; + +PromiseArray.prototype.getActualLength = function (len) { + return len; +}; + +return PromiseArray; +}; diff --git a/express-server/node_modules/bluebird/js/release/promisify.js b/express-server/node_modules/bluebird/js/release/promisify.js new file mode 100644 index 00000000..aa98e5bd --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/promisify.js @@ -0,0 +1,314 @@ +"use strict"; +module.exports = function(Promise, INTERNAL) { +var THIS = {}; +var util = require("./util"); +var nodebackForPromise = require("./nodeback"); +var withAppended = util.withAppended; +var maybeWrapAsError = util.maybeWrapAsError; +var canEvaluate = util.canEvaluate; +var TypeError = require("./errors").TypeError; +var defaultSuffix = "Async"; +var defaultPromisified = {__isPromisified__: true}; +var noCopyProps = [ + "arity", "length", + "name", + "arguments", + "caller", + "callee", + "prototype", + "__isPromisified__" +]; +var noCopyPropsPattern = new RegExp("^(?:" + noCopyProps.join("|") + ")$"); + +var defaultFilter = function(name) { + return util.isIdentifier(name) && + name.charAt(0) !== "_" && + name !== "constructor"; +}; + +function propsFilter(key) { + return !noCopyPropsPattern.test(key); +} + +function isPromisified(fn) { + try { + return fn.__isPromisified__ === true; + } + catch (e) { + return false; + } +} + +function hasPromisified(obj, key, suffix) { + var val = util.getDataPropertyOrDefault(obj, key + suffix, + defaultPromisified); + return val ? isPromisified(val) : false; +} +function checkValid(ret, suffix, suffixRegexp) { + for (var i = 0; i < ret.length; i += 2) { + var key = ret[i]; + if (suffixRegexp.test(key)) { + var keyWithoutAsyncSuffix = key.replace(suffixRegexp, ""); + for (var j = 0; j < ret.length; j += 2) { + if (ret[j] === keyWithoutAsyncSuffix) { + throw new TypeError("Cannot promisify an API that has normal methods with '%s'-suffix\u000a\u000a See http://goo.gl/MqrFmX\u000a" + .replace("%s", suffix)); + } + } + } + } +} + +function promisifiableMethods(obj, suffix, suffixRegexp, filter) { + var keys = util.inheritedDataKeys(obj); + var ret = []; + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + var value = obj[key]; + var passesDefaultFilter = filter === defaultFilter + ? true : defaultFilter(key, value, obj); + if (typeof value === "function" && + !isPromisified(value) && + !hasPromisified(obj, key, suffix) && + filter(key, value, obj, passesDefaultFilter)) { + ret.push(key, value); + } + } + checkValid(ret, suffix, suffixRegexp); + return ret; +} + +var escapeIdentRegex = function(str) { + return str.replace(/([$])/, "\\$"); +}; + +var makeNodePromisifiedEval; +if (!false) { +var switchCaseArgumentOrder = function(likelyArgumentCount) { + var ret = [likelyArgumentCount]; + var min = Math.max(0, likelyArgumentCount - 1 - 3); + for(var i = likelyArgumentCount - 1; i >= min; --i) { + ret.push(i); + } + for(var i = likelyArgumentCount + 1; i <= 3; ++i) { + ret.push(i); + } + return ret; +}; + +var argumentSequence = function(argumentCount) { + return util.filledRange(argumentCount, "_arg", ""); +}; + +var parameterDeclaration = function(parameterCount) { + return util.filledRange( + Math.max(parameterCount, 3), "_arg", ""); +}; + +var parameterCount = function(fn) { + if (typeof fn.length === "number") { + return Math.max(Math.min(fn.length, 1023 + 1), 0); + } + return 0; +}; + +makeNodePromisifiedEval = +function(callback, receiver, originalName, fn, _, multiArgs) { + var newParameterCount = Math.max(0, parameterCount(fn) - 1); + var argumentOrder = switchCaseArgumentOrder(newParameterCount); + var shouldProxyThis = typeof callback === "string" || receiver === THIS; + + function generateCallForArgumentCount(count) { + var args = argumentSequence(count).join(", "); + var comma = count > 0 ? ", " : ""; + var ret; + if (shouldProxyThis) { + ret = "ret = callback.call(this, {{args}}, nodeback); break;\n"; + } else { + ret = receiver === undefined + ? "ret = callback({{args}}, nodeback); break;\n" + : "ret = callback.call(receiver, {{args}}, nodeback); break;\n"; + } + return ret.replace("{{args}}", args).replace(", ", comma); + } + + function generateArgumentSwitchCase() { + var ret = ""; + for (var i = 0; i < argumentOrder.length; ++i) { + ret += "case " + argumentOrder[i] +":" + + generateCallForArgumentCount(argumentOrder[i]); + } + + ret += " \n\ + default: \n\ + var args = new Array(len + 1); \n\ + var i = 0; \n\ + for (var i = 0; i < len; ++i) { \n\ + args[i] = arguments[i]; \n\ + } \n\ + args[i] = nodeback; \n\ + [CodeForCall] \n\ + break; \n\ + ".replace("[CodeForCall]", (shouldProxyThis + ? "ret = callback.apply(this, args);\n" + : "ret = callback.apply(receiver, args);\n")); + return ret; + } + + var getFunctionCode = typeof callback === "string" + ? ("this != null ? this['"+callback+"'] : fn") + : "fn"; + var body = "'use strict'; \n\ + var ret = function (Parameters) { \n\ + 'use strict'; \n\ + var len = arguments.length; \n\ + var promise = new Promise(INTERNAL); \n\ + promise._captureStackTrace(); \n\ + var nodeback = nodebackForPromise(promise, " + multiArgs + "); \n\ + var ret; \n\ + var callback = tryCatch([GetFunctionCode]); \n\ + switch(len) { \n\ + [CodeForSwitchCase] \n\ + } \n\ + if (ret === errorObj) { \n\ + promise._rejectCallback(maybeWrapAsError(ret.e), true, true);\n\ + } \n\ + if (!promise._isFateSealed()) promise._setAsyncGuaranteed(); \n\ + return promise; \n\ + }; \n\ + notEnumerableProp(ret, '__isPromisified__', true); \n\ + return ret; \n\ + ".replace("[CodeForSwitchCase]", generateArgumentSwitchCase()) + .replace("[GetFunctionCode]", getFunctionCode); + body = body.replace("Parameters", parameterDeclaration(newParameterCount)); + return new Function("Promise", + "fn", + "receiver", + "withAppended", + "maybeWrapAsError", + "nodebackForPromise", + "tryCatch", + "errorObj", + "notEnumerableProp", + "INTERNAL", + body)( + Promise, + fn, + receiver, + withAppended, + maybeWrapAsError, + nodebackForPromise, + util.tryCatch, + util.errorObj, + util.notEnumerableProp, + INTERNAL); +}; +} + +function makeNodePromisifiedClosure(callback, receiver, _, fn, __, multiArgs) { + var defaultThis = (function() {return this;})(); + var method = callback; + if (typeof method === "string") { + callback = fn; + } + function promisified() { + var _receiver = receiver; + if (receiver === THIS) _receiver = this; + var promise = new Promise(INTERNAL); + promise._captureStackTrace(); + var cb = typeof method === "string" && this !== defaultThis + ? this[method] : callback; + var fn = nodebackForPromise(promise, multiArgs); + try { + cb.apply(_receiver, withAppended(arguments, fn)); + } catch(e) { + promise._rejectCallback(maybeWrapAsError(e), true, true); + } + if (!promise._isFateSealed()) promise._setAsyncGuaranteed(); + return promise; + } + util.notEnumerableProp(promisified, "__isPromisified__", true); + return promisified; +} + +var makeNodePromisified = canEvaluate + ? makeNodePromisifiedEval + : makeNodePromisifiedClosure; + +function promisifyAll(obj, suffix, filter, promisifier, multiArgs) { + var suffixRegexp = new RegExp(escapeIdentRegex(suffix) + "$"); + var methods = + promisifiableMethods(obj, suffix, suffixRegexp, filter); + + for (var i = 0, len = methods.length; i < len; i+= 2) { + var key = methods[i]; + var fn = methods[i+1]; + var promisifiedKey = key + suffix; + if (promisifier === makeNodePromisified) { + obj[promisifiedKey] = + makeNodePromisified(key, THIS, key, fn, suffix, multiArgs); + } else { + var promisified = promisifier(fn, function() { + return makeNodePromisified(key, THIS, key, + fn, suffix, multiArgs); + }); + util.notEnumerableProp(promisified, "__isPromisified__", true); + obj[promisifiedKey] = promisified; + } + } + util.toFastProperties(obj); + return obj; +} + +function promisify(callback, receiver, multiArgs) { + return makeNodePromisified(callback, receiver, undefined, + callback, null, multiArgs); +} + +Promise.promisify = function (fn, options) { + if (typeof fn !== "function") { + throw new TypeError("expecting a function but got " + util.classString(fn)); + } + if (isPromisified(fn)) { + return fn; + } + options = Object(options); + var receiver = options.context === undefined ? THIS : options.context; + var multiArgs = !!options.multiArgs; + var ret = promisify(fn, receiver, multiArgs); + util.copyDescriptors(fn, ret, propsFilter); + return ret; +}; + +Promise.promisifyAll = function (target, options) { + if (typeof target !== "function" && typeof target !== "object") { + throw new TypeError("the target of promisifyAll must be an object or a function\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + options = Object(options); + var multiArgs = !!options.multiArgs; + var suffix = options.suffix; + if (typeof suffix !== "string") suffix = defaultSuffix; + var filter = options.filter; + if (typeof filter !== "function") filter = defaultFilter; + var promisifier = options.promisifier; + if (typeof promisifier !== "function") promisifier = makeNodePromisified; + + if (!util.isIdentifier(suffix)) { + throw new RangeError("suffix must be a valid identifier\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + + var keys = util.inheritedDataKeys(target); + for (var i = 0; i < keys.length; ++i) { + var value = target[keys[i]]; + if (keys[i] !== "constructor" && + util.isClass(value)) { + promisifyAll(value.prototype, suffix, filter, promisifier, + multiArgs); + promisifyAll(value, suffix, filter, promisifier, multiArgs); + } + } + + return promisifyAll(target, suffix, filter, promisifier, multiArgs); +}; +}; + diff --git a/express-server/node_modules/bluebird/js/release/props.js b/express-server/node_modules/bluebird/js/release/props.js new file mode 100644 index 00000000..6a34aaf5 --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/props.js @@ -0,0 +1,118 @@ +"use strict"; +module.exports = function( + Promise, PromiseArray, tryConvertToPromise, apiRejection) { +var util = require("./util"); +var isObject = util.isObject; +var es5 = require("./es5"); +var Es6Map; +if (typeof Map === "function") Es6Map = Map; + +var mapToEntries = (function() { + var index = 0; + var size = 0; + + function extractEntry(value, key) { + this[index] = value; + this[index + size] = key; + index++; + } + + return function mapToEntries(map) { + size = map.size; + index = 0; + var ret = new Array(map.size * 2); + map.forEach(extractEntry, ret); + return ret; + }; +})(); + +var entriesToMap = function(entries) { + var ret = new Es6Map(); + var length = entries.length / 2 | 0; + for (var i = 0; i < length; ++i) { + var key = entries[length + i]; + var value = entries[i]; + ret.set(key, value); + } + return ret; +}; + +function PropertiesPromiseArray(obj) { + var isMap = false; + var entries; + if (Es6Map !== undefined && obj instanceof Es6Map) { + entries = mapToEntries(obj); + isMap = true; + } else { + var keys = es5.keys(obj); + var len = keys.length; + entries = new Array(len * 2); + for (var i = 0; i < len; ++i) { + var key = keys[i]; + entries[i] = obj[key]; + entries[i + len] = key; + } + } + this.constructor$(entries); + this._isMap = isMap; + this._init$(undefined, isMap ? -6 : -3); +} +util.inherits(PropertiesPromiseArray, PromiseArray); + +PropertiesPromiseArray.prototype._init = function () {}; + +PropertiesPromiseArray.prototype._promiseFulfilled = function (value, index) { + this._values[index] = value; + var totalResolved = ++this._totalResolved; + if (totalResolved >= this._length) { + var val; + if (this._isMap) { + val = entriesToMap(this._values); + } else { + val = {}; + var keyOffset = this.length(); + for (var i = 0, len = this.length(); i < len; ++i) { + val[this._values[i + keyOffset]] = this._values[i]; + } + } + this._resolve(val); + return true; + } + return false; +}; + +PropertiesPromiseArray.prototype.shouldCopyValues = function () { + return false; +}; + +PropertiesPromiseArray.prototype.getActualLength = function (len) { + return len >> 1; +}; + +function props(promises) { + var ret; + var castValue = tryConvertToPromise(promises); + + if (!isObject(castValue)) { + return apiRejection("cannot await properties of a non-object\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } else if (castValue instanceof Promise) { + ret = castValue._then( + Promise.props, undefined, undefined, undefined, undefined); + } else { + ret = new PropertiesPromiseArray(castValue).promise(); + } + + if (castValue instanceof Promise) { + ret._propagateFrom(castValue, 2); + } + return ret; +} + +Promise.prototype.props = function () { + return props(this); +}; + +Promise.props = function (promises) { + return props(promises); +}; +}; diff --git a/express-server/node_modules/bluebird/js/release/queue.js b/express-server/node_modules/bluebird/js/release/queue.js new file mode 100644 index 00000000..ffd36fda --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/queue.js @@ -0,0 +1,73 @@ +"use strict"; +function arrayMove(src, srcIndex, dst, dstIndex, len) { + for (var j = 0; j < len; ++j) { + dst[j + dstIndex] = src[j + srcIndex]; + src[j + srcIndex] = void 0; + } +} + +function Queue(capacity) { + this._capacity = capacity; + this._length = 0; + this._front = 0; +} + +Queue.prototype._willBeOverCapacity = function (size) { + return this._capacity < size; +}; + +Queue.prototype._pushOne = function (arg) { + var length = this.length(); + this._checkCapacity(length + 1); + var i = (this._front + length) & (this._capacity - 1); + this[i] = arg; + this._length = length + 1; +}; + +Queue.prototype.push = function (fn, receiver, arg) { + var length = this.length() + 3; + if (this._willBeOverCapacity(length)) { + this._pushOne(fn); + this._pushOne(receiver); + this._pushOne(arg); + return; + } + var j = this._front + length - 3; + this._checkCapacity(length); + var wrapMask = this._capacity - 1; + this[(j + 0) & wrapMask] = fn; + this[(j + 1) & wrapMask] = receiver; + this[(j + 2) & wrapMask] = arg; + this._length = length; +}; + +Queue.prototype.shift = function () { + var front = this._front, + ret = this[front]; + + this[front] = undefined; + this._front = (front + 1) & (this._capacity - 1); + this._length--; + return ret; +}; + +Queue.prototype.length = function () { + return this._length; +}; + +Queue.prototype._checkCapacity = function (size) { + if (this._capacity < size) { + this._resizeTo(this._capacity << 1); + } +}; + +Queue.prototype._resizeTo = function (capacity) { + var oldCapacity = this._capacity; + this._capacity = capacity; + var front = this._front; + var length = this._length; + var moveItemsCount = (front + length) & (oldCapacity - 1); + arrayMove(this, 0, this, oldCapacity, moveItemsCount); +}; + +module.exports = Queue; diff --git a/express-server/node_modules/bluebird/js/release/race.js b/express-server/node_modules/bluebird/js/release/race.js new file mode 100644 index 00000000..b862f46d --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/race.js @@ -0,0 +1,49 @@ +"use strict"; +module.exports = function( + Promise, INTERNAL, tryConvertToPromise, apiRejection) { +var util = require("./util"); + +var raceLater = function (promise) { + return promise.then(function(array) { + return race(array, promise); + }); +}; + +function race(promises, parent) { + var maybePromise = tryConvertToPromise(promises); + + if (maybePromise instanceof Promise) { + return raceLater(maybePromise); + } else { + promises = util.asArray(promises); + if (promises === null) + return apiRejection("expecting an array or an iterable object but got " + util.classString(promises)); + } + + var ret = new Promise(INTERNAL); + if (parent !== undefined) { + ret._propagateFrom(parent, 3); + } + var fulfill = ret._fulfill; + var reject = ret._reject; + for (var i = 0, len = promises.length; i < len; ++i) { + var val = promises[i]; + + if (val === undefined && !(i in promises)) { + continue; + } + + Promise.cast(val)._then(fulfill, reject, undefined, ret, null); + } + return ret; +} + +Promise.race = function (promises) { + return race(promises, undefined); +}; + +Promise.prototype.race = function () { + return race(this, undefined); +}; + +}; diff --git a/express-server/node_modules/bluebird/js/release/reduce.js b/express-server/node_modules/bluebird/js/release/reduce.js new file mode 100644 index 00000000..26e2b1a9 --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/reduce.js @@ -0,0 +1,172 @@ +"use strict"; +module.exports = function(Promise, + PromiseArray, + apiRejection, + tryConvertToPromise, + INTERNAL, + debug) { +var getDomain = Promise._getDomain; +var util = require("./util"); +var tryCatch = util.tryCatch; + +function ReductionPromiseArray(promises, fn, initialValue, _each) { + this.constructor$(promises); + var domain = getDomain(); + this._fn = domain === null ? fn : util.domainBind(domain, fn); + if (initialValue !== undefined) { + initialValue = Promise.resolve(initialValue); + initialValue._attachCancellationCallback(this); + } + this._initialValue = initialValue; + this._currentCancellable = null; + if(_each === INTERNAL) { + this._eachValues = Array(this._length); + } else if (_each === 0) { + this._eachValues = null; + } else { + this._eachValues = undefined; + } + this._promise._captureStackTrace(); + this._init$(undefined, -5); +} +util.inherits(ReductionPromiseArray, PromiseArray); + +ReductionPromiseArray.prototype._gotAccum = function(accum) { + if (this._eachValues !== undefined && + this._eachValues !== null && + accum !== INTERNAL) { + this._eachValues.push(accum); + } +}; + +ReductionPromiseArray.prototype._eachComplete = function(value) { + if (this._eachValues !== null) { + this._eachValues.push(value); + } + return this._eachValues; +}; + +ReductionPromiseArray.prototype._init = function() {}; + +ReductionPromiseArray.prototype._resolveEmptyArray = function() { + this._resolve(this._eachValues !== undefined ? this._eachValues + : this._initialValue); +}; + +ReductionPromiseArray.prototype.shouldCopyValues = function () { + return false; +}; + +ReductionPromiseArray.prototype._resolve = function(value) { + this._promise._resolveCallback(value); + this._values = null; +}; + +ReductionPromiseArray.prototype._resultCancelled = function(sender) { + if (sender === this._initialValue) return this._cancel(); + if (this._isResolved()) return; + this._resultCancelled$(); + if (this._currentCancellable instanceof Promise) { + this._currentCancellable.cancel(); + } + if (this._initialValue instanceof Promise) { + this._initialValue.cancel(); + } +}; + +ReductionPromiseArray.prototype._iterate = function (values) { + this._values = values; + var value; + var i; + var length = values.length; + if (this._initialValue !== undefined) { + value = this._initialValue; + i = 0; + } else { + value = Promise.resolve(values[0]); + i = 1; + } + + this._currentCancellable = value; + + if (!value.isRejected()) { + for (; i < length; ++i) { + var ctx = { + accum: null, + value: values[i], + index: i, + length: length, + array: this + }; + value = value._then(gotAccum, undefined, undefined, ctx, undefined); + } + } + + if (this._eachValues !== undefined) { + value = value + ._then(this._eachComplete, undefined, undefined, this, undefined); + } + value._then(completed, completed, undefined, value, this); +}; + +Promise.prototype.reduce = function (fn, initialValue) { + return reduce(this, fn, initialValue, null); +}; + +Promise.reduce = function (promises, fn, initialValue, _each) { + return reduce(promises, fn, initialValue, _each); +}; + +function completed(valueOrReason, array) { + if (this.isFulfilled()) { + array._resolve(valueOrReason); + } else { + array._reject(valueOrReason); + } +} + +function reduce(promises, fn, initialValue, _each) { + if (typeof fn !== "function") { + return apiRejection("expecting a function but got " + util.classString(fn)); + } + var array = new ReductionPromiseArray(promises, fn, initialValue, _each); + return array.promise(); +} + +function gotAccum(accum) { + this.accum = accum; + this.array._gotAccum(accum); + var value = tryConvertToPromise(this.value, this.array._promise); + if (value instanceof Promise) { + this.array._currentCancellable = value; + return value._then(gotValue, undefined, undefined, this, undefined); + } else { + return gotValue.call(this, value); + } +} + +function gotValue(value) { + var array = this.array; + var promise = array._promise; + var fn = tryCatch(array._fn); + promise._pushContext(); + var ret; + if (array._eachValues !== undefined) { + ret = fn.call(promise._boundValue(), value, this.index, this.length); + } else { + ret = fn.call(promise._boundValue(), + this.accum, value, this.index, this.length); + } + if (ret instanceof Promise) { + array._currentCancellable = ret; + } + var promiseCreated = promise._popContext(); + debug.checkForgottenReturns( + ret, + promiseCreated, + array._eachValues !== undefined ? "Promise.each" : "Promise.reduce", + promise + ); + return ret; +} +}; diff --git a/express-server/node_modules/bluebird/js/release/schedule.js b/express-server/node_modules/bluebird/js/release/schedule.js new file mode 100644 index 00000000..f70df9fc --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/schedule.js @@ -0,0 +1,61 @@ +"use strict"; +var util = require("./util"); +var schedule; +var noAsyncScheduler = function() { + throw new Error("No async scheduler available\u000a\u000a See http://goo.gl/MqrFmX\u000a"); +}; +var NativePromise = util.getNativePromise(); +if (util.isNode && typeof MutationObserver === "undefined") { + var GlobalSetImmediate = global.setImmediate; + var ProcessNextTick = process.nextTick; + schedule = util.isRecentNode + ? function(fn) { GlobalSetImmediate.call(global, fn); } + : function(fn) { ProcessNextTick.call(process, fn); }; +} else if (typeof NativePromise === "function" && + typeof NativePromise.resolve === "function") { + var nativePromise = NativePromise.resolve(); + schedule = function(fn) { + nativePromise.then(fn); + }; +} else if ((typeof MutationObserver !== "undefined") && + !(typeof window !== "undefined" && + window.navigator && + (window.navigator.standalone || window.cordova))) { + schedule = (function() { + var div = document.createElement("div"); + var opts = {attributes: true}; + var toggleScheduled = false; + var div2 = document.createElement("div"); + var o2 = new MutationObserver(function() { + div.classList.toggle("foo"); + toggleScheduled = false; + }); + o2.observe(div2, opts); + + var scheduleToggle = function() { + if (toggleScheduled) return; + toggleScheduled = true; + div2.classList.toggle("foo"); + }; + + return function schedule(fn) { + var o = new MutationObserver(function() { + o.disconnect(); + fn(); + }); + o.observe(div, opts); + scheduleToggle(); + }; + })(); +} else if (typeof setImmediate !== "undefined") { + schedule = function (fn) { + setImmediate(fn); + }; +} else if (typeof setTimeout !== "undefined") { + schedule = function (fn) { + setTimeout(fn, 0); + }; +} else { + schedule = noAsyncScheduler; +} +module.exports = schedule; diff --git a/express-server/node_modules/bluebird/js/release/settle.js b/express-server/node_modules/bluebird/js/release/settle.js new file mode 100644 index 00000000..fade3a17 --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/settle.js @@ -0,0 +1,43 @@ +"use strict"; +module.exports = + function(Promise, PromiseArray, debug) { +var PromiseInspection = Promise.PromiseInspection; +var util = require("./util"); + +function SettledPromiseArray(values) { + this.constructor$(values); +} +util.inherits(SettledPromiseArray, PromiseArray); + +SettledPromiseArray.prototype._promiseResolved = function (index, inspection) { + this._values[index] = inspection; + var totalResolved = ++this._totalResolved; + if (totalResolved >= this._length) { + this._resolve(this._values); + return true; + } + return false; +}; + +SettledPromiseArray.prototype._promiseFulfilled = function (value, index) { + var ret = new PromiseInspection(); + ret._bitField = 33554432; + ret._settledValueField = value; + return this._promiseResolved(index, ret); +}; +SettledPromiseArray.prototype._promiseRejected = function (reason, index) { + var ret = new PromiseInspection(); + ret._bitField = 16777216; + ret._settledValueField = reason; + return this._promiseResolved(index, ret); +}; + +Promise.settle = function (promises) { + debug.deprecated(".settle()", ".reflect()"); + return new SettledPromiseArray(promises).promise(); +}; + +Promise.prototype.settle = function () { + return Promise.settle(this); +}; +}; diff --git a/express-server/node_modules/bluebird/js/release/some.js b/express-server/node_modules/bluebird/js/release/some.js new file mode 100644 index 00000000..400d8520 --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/some.js @@ -0,0 +1,148 @@ +"use strict"; +module.exports = +function(Promise, PromiseArray, apiRejection) { +var util = require("./util"); +var RangeError = require("./errors").RangeError; +var AggregateError = require("./errors").AggregateError; +var isArray = util.isArray; +var CANCELLATION = {}; + + +function SomePromiseArray(values) { + this.constructor$(values); + this._howMany = 0; + this._unwrap = false; + this._initialized = false; +} +util.inherits(SomePromiseArray, PromiseArray); + +SomePromiseArray.prototype._init = function () { + if (!this._initialized) { + return; + } + if (this._howMany === 0) { + this._resolve([]); + return; + } + this._init$(undefined, -5); + var isArrayResolved = isArray(this._values); + if (!this._isResolved() && + isArrayResolved && + this._howMany > this._canPossiblyFulfill()) { + this._reject(this._getRangeError(this.length())); + } +}; + +SomePromiseArray.prototype.init = function () { + this._initialized = true; + this._init(); +}; + +SomePromiseArray.prototype.setUnwrap = function () { + this._unwrap = true; +}; + +SomePromiseArray.prototype.howMany = function () { + return this._howMany; +}; + +SomePromiseArray.prototype.setHowMany = function (count) { + this._howMany = count; +}; + +SomePromiseArray.prototype._promiseFulfilled = function (value) { + this._addFulfilled(value); + if (this._fulfilled() === this.howMany()) { + this._values.length = this.howMany(); + if (this.howMany() === 1 && this._unwrap) { + this._resolve(this._values[0]); + } else { + this._resolve(this._values); + } + return true; + } + return false; + +}; +SomePromiseArray.prototype._promiseRejected = function (reason) { + this._addRejected(reason); + return this._checkOutcome(); +}; + +SomePromiseArray.prototype._promiseCancelled = function () { + if (this._values instanceof Promise || this._values == null) { + return this._cancel(); + } + this._addRejected(CANCELLATION); + return this._checkOutcome(); +}; + +SomePromiseArray.prototype._checkOutcome = function() { + if (this.howMany() > this._canPossiblyFulfill()) { + var e = new AggregateError(); + for (var i = this.length(); i < this._values.length; ++i) { + if (this._values[i] !== CANCELLATION) { + e.push(this._values[i]); + } + } + if (e.length > 0) { + this._reject(e); + } else { + this._cancel(); + } + return true; + } + return false; +}; + +SomePromiseArray.prototype._fulfilled = function () { + return this._totalResolved; +}; + +SomePromiseArray.prototype._rejected = function () { + return this._values.length - this.length(); +}; + +SomePromiseArray.prototype._addRejected = function (reason) { + this._values.push(reason); +}; + +SomePromiseArray.prototype._addFulfilled = function (value) { + this._values[this._totalResolved++] = value; +}; + +SomePromiseArray.prototype._canPossiblyFulfill = function () { + return this.length() - this._rejected(); +}; + +SomePromiseArray.prototype._getRangeError = function (count) { + var message = "Input array must contain at least " + + this._howMany + " items but contains only " + count + " items"; + return new RangeError(message); +}; + +SomePromiseArray.prototype._resolveEmptyArray = function () { + this._reject(this._getRangeError(0)); +}; + +function some(promises, howMany) { + if ((howMany | 0) !== howMany || howMany < 0) { + return apiRejection("expecting a positive integer\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + var ret = new SomePromiseArray(promises); + var promise = ret.promise(); + ret.setHowMany(howMany); + ret.init(); + return promise; +} + +Promise.some = function (promises, howMany) { + return some(promises, howMany); +}; + +Promise.prototype.some = function (howMany) { + return some(this, howMany); +}; + +Promise._SomePromiseArray = SomePromiseArray; +}; diff --git a/express-server/node_modules/bluebird/js/release/synchronous_inspection.js b/express-server/node_modules/bluebird/js/release/synchronous_inspection.js new file mode 100644 index 00000000..9c49d2e6 --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/synchronous_inspection.js @@ -0,0 +1,103 @@ +"use strict"; +module.exports = function(Promise) { +function PromiseInspection(promise) { + if (promise !== undefined) { + promise = promise._target(); + this._bitField = promise._bitField; + this._settledValueField = promise._isFateSealed() + ? promise._settledValue() : undefined; + } + else { + this._bitField = 0; + this._settledValueField = undefined; + } +} + +PromiseInspection.prototype._settledValue = function() { + return this._settledValueField; +}; + +var value = PromiseInspection.prototype.value = function () { + if (!this.isFulfilled()) { + throw new TypeError("cannot get fulfillment value of a non-fulfilled promise\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + return this._settledValue(); +}; + +var reason = PromiseInspection.prototype.error = +PromiseInspection.prototype.reason = function () { + if (!this.isRejected()) { + throw new TypeError("cannot get rejection reason of a non-rejected promise\u000a\u000a See http://goo.gl/MqrFmX\u000a"); + } + return this._settledValue(); +}; + +var isFulfilled = PromiseInspection.prototype.isFulfilled = function() { + return (this._bitField & 33554432) !== 0; +}; + +var isRejected = PromiseInspection.prototype.isRejected = function () { + return (this._bitField & 16777216) !== 0; +}; + +var isPending = PromiseInspection.prototype.isPending = function () { + return (this._bitField & 50397184) === 0; +}; + +var isResolved = PromiseInspection.prototype.isResolved = function () { + return (this._bitField & 50331648) !== 0; +}; + +PromiseInspection.prototype.isCancelled = function() { + return (this._bitField & 8454144) !== 0; +}; + +Promise.prototype.__isCancelled = function() { + return (this._bitField & 65536) === 65536; +}; + +Promise.prototype._isCancelled = function() { + return this._target().__isCancelled(); +}; + +Promise.prototype.isCancelled = function() { + return (this._target()._bitField & 8454144) !== 0; +}; + +Promise.prototype.isPending = function() { + return isPending.call(this._target()); +}; + +Promise.prototype.isRejected = function() { + return isRejected.call(this._target()); +}; + +Promise.prototype.isFulfilled = function() { + return isFulfilled.call(this._target()); +}; + +Promise.prototype.isResolved = function() { + return isResolved.call(this._target()); +}; + +Promise.prototype.value = function() { + return value.call(this._target()); +}; + +Promise.prototype.reason = function() { + var target = this._target(); + target._unsetRejectionIsUnhandled(); + return reason.call(target); +}; + +Promise.prototype._value = function() { + return this._settledValue(); +}; + +Promise.prototype._reason = function() { + this._unsetRejectionIsUnhandled(); + return this._settledValue(); +}; + +Promise.PromiseInspection = PromiseInspection; +}; diff --git a/express-server/node_modules/bluebird/js/release/thenables.js b/express-server/node_modules/bluebird/js/release/thenables.js new file mode 100644 index 00000000..d6ab9aa2 --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/thenables.js @@ -0,0 +1,86 @@ +"use strict"; +module.exports = function(Promise, INTERNAL) { +var util = require("./util"); +var errorObj = util.errorObj; +var isObject = util.isObject; + +function tryConvertToPromise(obj, context) { + if (isObject(obj)) { + if (obj instanceof Promise) return obj; + var then = getThen(obj); + if (then === errorObj) { + if (context) context._pushContext(); + var ret = Promise.reject(then.e); + if (context) context._popContext(); + return ret; + } else if (typeof then === "function") { + if (isAnyBluebirdPromise(obj)) { + var ret = new Promise(INTERNAL); + obj._then( + ret._fulfill, + ret._reject, + undefined, + ret, + null + ); + return ret; + } + return doThenable(obj, then, context); + } + } + return obj; +} + +function doGetThen(obj) { + return obj.then; +} + +function getThen(obj) { + try { + return doGetThen(obj); + } catch (e) { + errorObj.e = e; + return errorObj; + } +} + +var hasProp = {}.hasOwnProperty; +function isAnyBluebirdPromise(obj) { + try { + return hasProp.call(obj, "_promise0"); + } catch (e) { + return false; + } +} + +function doThenable(x, then, context) { + var promise = new Promise(INTERNAL); + var ret = promise; + if (context) context._pushContext(); + promise._captureStackTrace(); + if (context) context._popContext(); + var synchronous = true; + var result = util.tryCatch(then).call(x, resolve, reject); + synchronous = false; + + if (promise && result === errorObj) { + promise._rejectCallback(result.e, true, true); + promise = null; + } + + function resolve(value) { + if (!promise) return; + promise._resolveCallback(value); + promise = null; + } + + function reject(reason) { + if (!promise) return; + promise._rejectCallback(reason, synchronous, true); + promise = null; + } + return ret; +} + +return tryConvertToPromise; +}; diff --git a/express-server/node_modules/bluebird/js/release/timers.js b/express-server/node_modules/bluebird/js/release/timers.js new file mode 100644 index 00000000..cb8f1f42 --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/timers.js @@ -0,0 +1,93 @@ +"use strict"; +module.exports = function(Promise, INTERNAL, debug) { +var util = require("./util"); +var TimeoutError = Promise.TimeoutError; + +function HandleWrapper(handle) { + this.handle = handle; +} + +HandleWrapper.prototype._resultCancelled = function() { + clearTimeout(this.handle); +}; + +var afterValue = function(value) { return delay(+this).thenReturn(value); }; +var delay = Promise.delay = function (ms, value) { + var ret; + var handle; + if (value !== undefined) { + ret = Promise.resolve(value) + ._then(afterValue, null, null, ms, undefined); + if (debug.cancellation() && value instanceof Promise) { + ret._setOnCancel(value); + } + } else { + ret = new Promise(INTERNAL); + handle = setTimeout(function() { ret._fulfill(); }, +ms); + if (debug.cancellation()) { + ret._setOnCancel(new HandleWrapper(handle)); + } + ret._captureStackTrace(); + } + ret._setAsyncGuaranteed(); + return ret; +}; + +Promise.prototype.delay = function (ms) { + return delay(ms, this); +}; + +var afterTimeout = function (promise, message, parent) { + var err; + if (typeof message !== "string") { + if (message instanceof Error) { + err = message; + } else { + err = new TimeoutError("operation timed out"); + } + } else { + err = new TimeoutError(message); + } + util.markAsOriginatingFromRejection(err); + promise._attachExtraTrace(err); + promise._reject(err); + + if (parent != null) { + parent.cancel(); + } +}; + +function successClear(value) { + clearTimeout(this.handle); + return value; +} + +function failureClear(reason) { + clearTimeout(this.handle); + throw reason; +} + +Promise.prototype.timeout = function (ms, message) { + ms = +ms; + var ret, parent; + + var handleWrapper = new HandleWrapper(setTimeout(function timeoutTimeout() { + if (ret.isPending()) { + afterTimeout(ret, message, parent); + } + }, ms)); + + if (debug.cancellation()) { + parent = this.then(); + ret = parent._then(successClear, failureClear, + undefined, handleWrapper, undefined); + ret._setOnCancel(handleWrapper); + } else { + ret = this._then(successClear, failureClear, + undefined, handleWrapper, undefined); + } + + return ret; +}; + +}; diff --git a/express-server/node_modules/bluebird/js/release/using.js b/express-server/node_modules/bluebird/js/release/using.js new file mode 100644 index 00000000..65de531c --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/using.js @@ -0,0 +1,226 @@ +"use strict"; +module.exports = function (Promise, apiRejection, tryConvertToPromise, + createContext, INTERNAL, debug) { + var util = require("./util"); + var TypeError = require("./errors").TypeError; + var inherits = require("./util").inherits; + var errorObj = util.errorObj; + var tryCatch = util.tryCatch; + var NULL = {}; + + function thrower(e) { + setTimeout(function(){throw e;}, 0); + } + + function castPreservingDisposable(thenable) { + var maybePromise = tryConvertToPromise(thenable); + if (maybePromise !== thenable && + typeof thenable._isDisposable === "function" && + typeof thenable._getDisposer === "function" && + thenable._isDisposable()) { + maybePromise._setDisposable(thenable._getDisposer()); + } + return maybePromise; + } + function dispose(resources, inspection) { + var i = 0; + var len = resources.length; + var ret = new Promise(INTERNAL); + function iterator() { + if (i >= len) return ret._fulfill(); + var maybePromise = castPreservingDisposable(resources[i++]); + if (maybePromise instanceof Promise && + maybePromise._isDisposable()) { + try { + maybePromise = tryConvertToPromise( + maybePromise._getDisposer().tryDispose(inspection), + resources.promise); + } catch (e) { + return thrower(e); + } + if (maybePromise instanceof Promise) { + return maybePromise._then(iterator, thrower, + null, null, null); + } + } + iterator(); + } + iterator(); + return ret; + } + + function Disposer(data, promise, context) { + this._data = data; + this._promise = promise; + this._context = context; + } + + Disposer.prototype.data = function () { + return this._data; + }; + + Disposer.prototype.promise = function () { + return this._promise; + }; + + Disposer.prototype.resource = function () { + if (this.promise().isFulfilled()) { + return this.promise().value(); + } + return NULL; + }; + + Disposer.prototype.tryDispose = function(inspection) { + var resource = this.resource(); + var context = this._context; + if (context !== undefined) context._pushContext(); + var ret = resource !== NULL + ? this.doDispose(resource, inspection) : null; + if (context !== undefined) context._popContext(); + this._promise._unsetDisposable(); + this._data = null; + return ret; + }; + + Disposer.isDisposer = function (d) { + return (d != null && + typeof d.resource === "function" && + typeof d.tryDispose === "function"); + }; + + function FunctionDisposer(fn, promise, context) { + this.constructor$(fn, promise, context); + } + inherits(FunctionDisposer, Disposer); + + FunctionDisposer.prototype.doDispose = function (resource, inspection) { + var fn = this.data(); + return fn.call(resource, resource, inspection); + }; + + function maybeUnwrapDisposer(value) { + if (Disposer.isDisposer(value)) { + this.resources[this.index]._setDisposable(value); + return value.promise(); + } + return value; + } + + function ResourceList(length) { + this.length = length; + this.promise = null; + this[length-1] = null; + } + + ResourceList.prototype._resultCancelled = function() { + var len = this.length; + for (var i = 0; i < len; ++i) { + var item = this[i]; + if (item instanceof Promise) { + item.cancel(); + } + } + }; + + Promise.using = function () { + var len = arguments.length; + if (len < 2) return apiRejection( + "you must pass at least 2 arguments to Promise.using"); + var fn = arguments[len - 1]; + if (typeof fn !== "function") { + return apiRejection("expecting a function but got " + util.classString(fn)); + } + var input; + var spreadArgs = true; + if (len === 2 && Array.isArray(arguments[0])) { + input = arguments[0]; + len = input.length; + spreadArgs = false; + } else { + input = arguments; + len--; + } + var resources = new ResourceList(len); + for (var i = 0; i < len; ++i) { + var resource = input[i]; + if (Disposer.isDisposer(resource)) { + var disposer = resource; + resource = resource.promise(); + resource._setDisposable(disposer); + } else { + var maybePromise = tryConvertToPromise(resource); + if (maybePromise instanceof Promise) { + resource = + maybePromise._then(maybeUnwrapDisposer, null, null, { + resources: resources, + index: i + }, undefined); + } + } + resources[i] = resource; + } + + var reflectedResources = new Array(resources.length); + for (var i = 0; i < reflectedResources.length; ++i) { + reflectedResources[i] = Promise.resolve(resources[i]).reflect(); + } + + var resultPromise = Promise.all(reflectedResources) + .then(function(inspections) { + for (var i = 0; i < inspections.length; ++i) { + var inspection = inspections[i]; + if (inspection.isRejected()) { + errorObj.e = inspection.error(); + return errorObj; + } else if (!inspection.isFulfilled()) { + resultPromise.cancel(); + return; + } + inspections[i] = inspection.value(); + } + promise._pushContext(); + + fn = tryCatch(fn); + var ret = spreadArgs + ? fn.apply(undefined, inspections) : fn(inspections); + var promiseCreated = promise._popContext(); + debug.checkForgottenReturns( + ret, promiseCreated, "Promise.using", promise); + return ret; + }); + + var promise = resultPromise.lastly(function() { + var inspection = new Promise.PromiseInspection(resultPromise); + return dispose(resources, inspection); + }); + resources.promise = promise; + promise._setOnCancel(resources); + return promise; + }; + + Promise.prototype._setDisposable = function (disposer) { + this._bitField = this._bitField | 131072; + this._disposer = disposer; + }; + + Promise.prototype._isDisposable = function () { + return (this._bitField & 131072) > 0; + }; + + Promise.prototype._getDisposer = function () { + return this._disposer; + }; + + Promise.prototype._unsetDisposable = function () { + this._bitField = this._bitField & (~131072); + this._disposer = undefined; + }; + + Promise.prototype.disposer = function (fn) { + if (typeof fn === "function") { + return new FunctionDisposer(fn, this, createContext()); + } + throw new TypeError(); + }; + +}; diff --git a/express-server/node_modules/bluebird/js/release/util.js b/express-server/node_modules/bluebird/js/release/util.js new file mode 100644 index 00000000..c5617ee8 --- /dev/null +++ b/express-server/node_modules/bluebird/js/release/util.js @@ -0,0 +1,384 @@ +"use strict"; +var es5 = require("./es5"); +var canEvaluate = typeof navigator == "undefined"; + +var errorObj = {e: {}}; +var tryCatchTarget; +var globalObject = typeof self !== "undefined" ? self : + typeof window !== "undefined" ? window : + typeof global !== "undefined" ? global : + this !== undefined ? this : null; + +function tryCatcher() { + try { + var target = tryCatchTarget; + tryCatchTarget = null; + return target.apply(this, arguments); + } catch (e) { + errorObj.e = e; + return errorObj; + } +} +function tryCatch(fn) { + tryCatchTarget = fn; + return tryCatcher; +} + +var inherits = function(Child, Parent) { + var hasProp = {}.hasOwnProperty; + + function T() { + this.constructor = Child; + this.constructor$ = Parent; + for (var propertyName in Parent.prototype) { + if (hasProp.call(Parent.prototype, propertyName) && + propertyName.charAt(propertyName.length-1) !== "$" + ) { + this[propertyName + "$"] = Parent.prototype[propertyName]; + } + } + } + T.prototype = Parent.prototype; + Child.prototype = new T(); + return Child.prototype; +}; + + +function isPrimitive(val) { + return val == null || val === true || val === false || + typeof val === "string" || typeof val === "number"; + +} + +function isObject(value) { + return typeof value === "function" || + typeof value === "object" && value !== null; +} + +function maybeWrapAsError(maybeError) { + if (!isPrimitive(maybeError)) return maybeError; + + return new Error(safeToString(maybeError)); +} + +function withAppended(target, appendee) { + var len = target.length; + var ret = new Array(len + 1); + var i; + for (i = 0; i < len; ++i) { + ret[i] = target[i]; + } + ret[i] = appendee; + return ret; +} + +function getDataPropertyOrDefault(obj, key, defaultValue) { + if (es5.isES5) { + var desc = Object.getOwnPropertyDescriptor(obj, key); + + if (desc != null) { + return desc.get == null && desc.set == null + ? desc.value + : defaultValue; + } + } else { + return {}.hasOwnProperty.call(obj, key) ? obj[key] : undefined; + } +} + +function notEnumerableProp(obj, name, value) { + if (isPrimitive(obj)) return obj; + var descriptor = { + value: value, + configurable: true, + enumerable: false, + writable: true + }; + es5.defineProperty(obj, name, descriptor); + return obj; +} + +function thrower(r) { + throw r; +} + +var inheritedDataKeys = (function() { + var excludedPrototypes = [ + Array.prototype, + Object.prototype, + Function.prototype + ]; + + var isExcludedProto = function(val) { + for (var i = 0; i < excludedPrototypes.length; ++i) { + if (excludedPrototypes[i] === val) { + return true; + } + } + return false; + }; + + if (es5.isES5) { + var getKeys = Object.getOwnPropertyNames; + return function(obj) { + var ret = []; + var visitedKeys = Object.create(null); + while (obj != null && !isExcludedProto(obj)) { + var keys; + try { + keys = getKeys(obj); + } catch (e) { + return ret; + } + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (visitedKeys[key]) continue; + visitedKeys[key] = true; + var desc = Object.getOwnPropertyDescriptor(obj, key); + if (desc != null && desc.get == null && desc.set == null) { + ret.push(key); + } + } + obj = es5.getPrototypeOf(obj); + } + return ret; + }; + } else { + var hasProp = {}.hasOwnProperty; + return function(obj) { + if (isExcludedProto(obj)) return []; + var ret = []; + + /*jshint forin:false */ + enumeration: for (var key in obj) { + if (hasProp.call(obj, key)) { + ret.push(key); + } else { + for (var i = 0; i < excludedPrototypes.length; ++i) { + if (hasProp.call(excludedPrototypes[i], key)) { + continue enumeration; + } + } + ret.push(key); + } + } + return ret; + }; + } + +})(); + +var thisAssignmentPattern = /this\s*\.\s*\S+\s*=/; +function isClass(fn) { + try { + if (typeof fn === "function") { + var keys = es5.names(fn.prototype); + + var hasMethods = es5.isES5 && keys.length > 1; + var hasMethodsOtherThanConstructor = keys.length > 0 && + !(keys.length === 1 && keys[0] === "constructor"); + var hasThisAssignmentAndStaticMethods = + thisAssignmentPattern.test(fn + "") && es5.names(fn).length > 0; + + if (hasMethods || hasMethodsOtherThanConstructor || + hasThisAssignmentAndStaticMethods) { + return true; + } + } + return false; + } catch (e) { + return false; + } +} + +function toFastProperties(obj) { + /*jshint -W027,-W055,-W031*/ + function FakeConstructor() {} + FakeConstructor.prototype = obj; + var receiver = new FakeConstructor(); + function ic() { + return typeof receiver.foo; + } + ic(); + ic(); + return obj; + eval(obj); +} + +var rident = /^[a-z$_][a-z$_0-9]*$/i; +function isIdentifier(str) { + return rident.test(str); +} + +function filledRange(count, prefix, suffix) { + var ret = new Array(count); + for(var i = 0; i < count; ++i) { + ret[i] = prefix + i + suffix; + } + return ret; +} + +function safeToString(obj) { + try { + return obj + ""; + } catch (e) { + return "[no string representation]"; + } +} + +function isError(obj) { + return obj instanceof Error || + (obj !== null && + typeof obj === "object" && + typeof obj.message === "string" && + typeof obj.name === "string"); +} + +function markAsOriginatingFromRejection(e) { + try { + notEnumerableProp(e, "isOperational", true); + } + catch(ignore) {} +} + +function originatesFromRejection(e) { + if (e == null) return false; + return ((e instanceof Error["__BluebirdErrorTypes__"].OperationalError) || + e["isOperational"] === true); +} + +function canAttachTrace(obj) { + return isError(obj) && es5.propertyIsWritable(obj, "stack"); +} + +var ensureErrorObject = (function() { + if (!("stack" in new Error())) { + return function(value) { + if (canAttachTrace(value)) return value; + try {throw new Error(safeToString(value));} + catch(err) {return err;} + }; + } else { + return function(value) { + if (canAttachTrace(value)) return value; + return new Error(safeToString(value)); + }; + } +})(); + +function classString(obj) { + return {}.toString.call(obj); +} + +function copyDescriptors(from, to, filter) { + var keys = es5.names(from); + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (filter(key)) { + try { + es5.defineProperty(to, key, es5.getDescriptor(from, key)); + } catch (ignore) {} + } + } +} + +var asArray = function(v) { + if (es5.isArray(v)) { + return v; + } + return null; +}; + +if (typeof Symbol !== "undefined" && Symbol.iterator) { + var ArrayFrom = typeof Array.from === "function" ? function(v) { + return Array.from(v); + } : function(v) { + var ret = []; + var it = v[Symbol.iterator](); + var itResult; + while (!((itResult = it.next()).done)) { + ret.push(itResult.value); + } + return ret; + }; + + asArray = function(v) { + if (es5.isArray(v)) { + return v; + } else if (v != null && typeof v[Symbol.iterator] === "function") { + return ArrayFrom(v); + } + return null; + }; +} + +var isNode = typeof process !== "undefined" && + classString(process).toLowerCase() === "[object process]"; + +var hasEnvVariables = typeof process !== "undefined" && + typeof process.env !== "undefined"; + +function env(key) { + return hasEnvVariables ? process.env[key] : undefined; +} + +function getNativePromise() { + if (typeof Promise === "function") { + try { + var promise = new Promise(function(){}); + if ({}.toString.call(promise) === "[object Promise]") { + return Promise; + } + } catch (e) {} + } +} + +function domainBind(self, cb) { + return self.bind(cb); +} + +var ret = { + isClass: isClass, + isIdentifier: isIdentifier, + inheritedDataKeys: inheritedDataKeys, + getDataPropertyOrDefault: getDataPropertyOrDefault, + thrower: thrower, + isArray: es5.isArray, + asArray: asArray, + notEnumerableProp: notEnumerableProp, + isPrimitive: isPrimitive, + isObject: isObject, + isError: isError, + canEvaluate: canEvaluate, + errorObj: errorObj, + tryCatch: tryCatch, + inherits: inherits, + withAppended: withAppended, + maybeWrapAsError: maybeWrapAsError, + toFastProperties: toFastProperties, + filledRange: filledRange, + toString: safeToString, + canAttachTrace: canAttachTrace, + ensureErrorObject: ensureErrorObject, + originatesFromRejection: originatesFromRejection, + markAsOriginatingFromRejection: markAsOriginatingFromRejection, + classString: classString, + copyDescriptors: copyDescriptors, + hasDevTools: typeof chrome !== "undefined" && chrome && + typeof chrome.loadTimes === "function", + isNode: isNode, + hasEnvVariables: hasEnvVariables, + env: env, + global: globalObject, + getNativePromise: getNativePromise, + domainBind: domainBind +}; +ret.isRecentNode = ret.isNode && (function() { + var version = process.versions.node.split(".").map(Number); + return (version[0] === 0 && version[1] > 10) || (version[0] > 0); +})(); + +if (ret.isNode) ret.toFastProperties(process); + +try {throw new Error(); } catch (e) {ret.lastLineError = e;} +module.exports = ret; diff --git a/express-server/node_modules/bluebird/package.json b/express-server/node_modules/bluebird/package.json new file mode 100644 index 00000000..89b8a3b3 --- /dev/null +++ b/express-server/node_modules/bluebird/package.json @@ -0,0 +1,130 @@ +{ + "_args": [ + [ + "bluebird@^3.5.1", + "/nodeapps/https-test/greenlock-express.js/node_modules/le-sni-auto" + ] + ], + "_from": "bluebird@>=3.5.1 <4.0.0", + "_hasShrinkwrap": false, + "_id": "bluebird@3.5.3", + "_inCache": true, + "_installable": true, + "_location": "/bluebird", + "_nodeVersion": "8.0.0", + "_npmOperationalInternal": { + "host": "s3://npm-registry-packages", + "tmp": "tmp/bluebird_3.5.3_1541534782293_0.44984806474241434" + }, + "_npmUser": { + "email": "petka_antonov@hotmail.com", + "name": "esailija" + }, + "_npmVersion": "5.0.2", + "_phantomChildren": {}, + "_requested": { + "name": "bluebird", + "raw": "bluebird@^3.5.1", + "rawSpec": "^3.5.1", + "scope": null, + "spec": ">=3.5.1 <4.0.0", + "type": "range" + }, + "_requiredBy": [ + "/le-sni-auto" + ], + "_resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", + "_shasum": "7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7", + "_shrinkwrap": null, + "_spec": "bluebird@^3.5.1", + "_where": "/nodeapps/https-test/greenlock-express.js/node_modules/le-sni-auto", + "author": { + "email": "petka_antonov@hotmail.com", + "name": "Petka Antonov", + "url": "http://github.com/petkaantonov/" + }, + "browser": "./js/browser/bluebird.js", + "bugs": { + "url": "http://github.com/petkaantonov/bluebird/issues" + }, + "dependencies": {}, + "description": "Full featured Promises/A+ implementation with exceptionally good performance", + "devDependencies": { + "acorn": "^6.0.2", + "acorn-walk": "^6.1.0", + "baconjs": "^0.7.43", + "bluebird": "^2.9.2", + "body-parser": "^1.10.2", + "browserify": "^8.1.1", + "cli-table": "~0.3.1", + "co": "^4.2.0", + "cross-spawn": "^0.2.3", + "glob": "^4.3.2", + "grunt-saucelabs": "~8.4.1", + "highland": "^2.3.0", + "istanbul": "^0.3.5", + "jshint": "^2.6.0", + "jshint-stylish": "~0.2.0", + "kefir": "^2.4.1", + "mkdirp": "~0.5.0", + "mocha": "~2.1", + "open": "~0.0.5", + "optimist": "~0.6.1", + "rimraf": "~2.2.6", + "rx": "^2.3.25", + "serve-static": "^1.7.1", + "sinon": "~1.7.3", + "uglify-js": "~2.4.16" + }, + "directories": {}, + "dist": { + "fileCount": 45, + "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", + "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb4fQ/CRA9TVsSAnZWagAADEQP/11qhHpnP8KOMd15DjrY\nEWaCpiAdbz1FxinDaWkBU7KehUL4ae5KBfMWi7xh0PuSBvL5aPCOkVApU6KO\nnI/qpOOKAl+PafeGHn/pV89cq5fMNV9L25F2JNmP6B8z9d4WH1NkvA/0Uvrg\nA5huMmg2UbuhKhRG3aDHJpWbZfYure2L4MwUt6ohCnzJvEeYotOrQFhENxCH\nYt0QwLwijJU01UqRGF4bdNm/PfVQBbRRn8yLsarDTM0L6fFmRuRVeonTsU7U\nthNuti8QkbMwvvbsatRMin6bPVY9uM1IlqTFAIqJCJ3vjRPgICWTOAfdB9X/\nhMP5K/yAvTnAx1COLZiYtlc/9w4O77i7/s9NIAxNaUR7QvYXtDYRsZIdEH9W\nR8RIA6DyOgx/juCbO1ow6ipFux+EShMQPLFVJhMIoaguOdhOuKGPnkHwJaC2\nhNiHP6AYwEjxIAnHWNBcmjDceGQGCzYsB4m59trpWdKswqrAjfmsQ0aDjYNZ\nPkcmE7qTrTxIPE/Ven/pdgIr/NBAYh/CIFnNI7jY80UmuXQVU0LmSs0MicvR\nfcL2VUjnNEhShomb7vm3u5NBXABTb/EP8x9+zj72F8pcgLZkjuOI458cZYeE\nFD/8iNGihwyEeiBY81yhTGThz0CgR42f8YiM4tZakAzwhhZ0RGCT2ypkXx9t\nWtsm\r\n=OXad\r\n-----END PGP SIGNATURE-----\r\n", + "shasum": "7d01c6f9616c9a51ab0f8c549a79dfe6ec33efa7", + "tarball": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", + "unpackedSize": 620138 + }, + "gitHead": "a5a5b57e82f1937566e0384206219768b4e8672c", + "homepage": "https://github.com/petkaantonov/bluebird", + "keywords": [ + "async", + "await", + "deferred", + "deferreds", + "dsl", + "flow control", + "fluent interface", + "future", + "performance", + "promise", + "promises", + "promises-a", + "promises-aplus" + ], + "license": "MIT", + "main": "./js/release/bluebird.js", + "maintainers": [ + { + "name": "esailija", + "email": "petka_antonov@hotmail.com" + } + ], + "name": "bluebird", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/petkaantonov/bluebird.git" + }, + "scripts": { + "generate-browser-core": "node tools/build.js --features=core --no-debug --release --zalgo --browser --minify && mv js/browser/bluebird.js js/browser/bluebird.core.js && mv js/browser/bluebird.min.js js/browser/bluebird.core.min.js", + "generate-browser-full": "node tools/build.js --no-clean --no-debug --release --browser --minify", + "istanbul": "istanbul", + "lint": "node scripts/jshint.js", + "prepublish": "npm run generate-browser-core && npm run generate-browser-full", + "test": "node --expose-gc tools/test.js" + }, + "version": "3.5.3", + "webpack": "./js/release/bluebird.js" +} diff --git a/express-server/node_modules/certpem/LICENSE b/express-server/node_modules/certpem/LICENSE new file mode 100644 index 00000000..a7782bc5 --- /dev/null +++ b/express-server/node_modules/certpem/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 Daplie, Inc + +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/express-server/node_modules/certpem/README.md b/express-server/node_modules/certpem/README.md new file mode 100644 index 00000000..469d9bd0 --- /dev/null +++ b/express-server/node_modules/certpem/README.md @@ -0,0 +1,65 @@ +cert-info.js +============ + +Read basic info from a cert.pem / x509 certificate. + +Used for [Greenlock.js](https://git.coolaj86.com/coolaj86/greenlock-express.js) + +Install +======= + +```bash +# bin +npm install --global certpem + +# node.js library +npm install --save certpem +``` + +Usage +===== + +CLI +--- + +For basic info (subject, altnames, issuedAt, expiresAt): + +```bash +certpem /path/to/cert.pem +``` + +Output all info by passing `--debug` or use `--json` to see the basic info pretty-printed. + +node.js +------- + +```javascript +'use strict'; + +var certpem = require('certpem').certpem +var cert = fs.readFile('cert.pem', 'ascii', function (err, certstr) { + + // basic info + console.info(certpem.info(certstr)); + + // way too much info + // (requires npm install --save node.extend@1) + console.info(certpem.debug(certstr)); + +}); +``` + +Example output: + +```javascript +{ + "subject": "localhost.daplie.com", + "altnames": [ + "localhost.daplie.com" + ], + "issuedAt": 1465516800000, + "expiresAt": 1499731199000 +} +``` + +With a few small changes this could also work in the browser (that's how its dependencies are designed). diff --git a/express-server/node_modules/certpem/bin/certpem.js b/express-server/node_modules/certpem/bin/certpem.js new file mode 100644 index 00000000..a5f556fb --- /dev/null +++ b/express-server/node_modules/certpem/bin/certpem.js @@ -0,0 +1,52 @@ +#!/usr/bin/env node + +'use strict'; + +var certpem = require('../').certpem; +var path = require('path'); +var filepath = (process.cwd() + path.sep + 'cert.pem'); +var debug = false; +var json; +var cert; + +if (/--debug/.test(process.argv[2]) || /--debug/.test(process.argv[3])) { + debug = true; +} +if (/--json/.test(process.argv[2]) || /--json/.test(process.argv[3])) { + json = true; +} +if (process.argv[2] && !/^--/.test(process.argv[2])) { + filepath = process.argv[2]; +} +if (process.argv[3] && !/^--/.test(process.argv[3])) { + filepath = process.argv[3]; +} + +if (filepath.length > 256) { + cert = filepath; +} +else { + cert = require('fs').readFileSync(filepath, 'ascii'); +} + +if (debug) { + console.info(JSON.stringify(certpem.debug(cert), null, ' ')); +} else { + var c = certpem.info(cert); + + if (json) { + console.info(JSON.stringify(c, null, ' ')); + return; + } + + console.info(''); + + console.info('Certificate for', c.subject); + console.info(''); + console.info('Altnames:', c.altnames.join(', ')); + console.info(''); + console.info('Issued at', new Date(c.issuedAt)); + console.info('Expires at', new Date(c.expiresAt)); + + console.info(''); +} diff --git a/express-server/node_modules/certpem/cert.pem b/express-server/node_modules/certpem/cert.pem new file mode 100644 index 00000000..4d3bcb33 --- /dev/null +++ b/express-server/node_modules/certpem/cert.pem @@ -0,0 +1,31 @@ +-----BEGIN CERTIFICATE----- +MIIFajCCBFKgAwIBAgIQdsKX6kswrkbK7NZ/kc31vTANBgkqhkiG9w0BAQsFADBC +MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMS +UmFwaWRTU0wgU0hBMjU2IENBMB4XDTE2MDYxMDAwMDAwMFoXDTE3MDcxMDIzNTk1 +OVowHzEdMBsGA1UEAwwUbG9jYWxob3N0LmRhcGxpZS5jb20wggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCd49Z2PuWyX9qFlURgq8E0OzMP6szDLutkYBmW +sDdnekEw0mAUgmXcrhKcDog8ugDvcVqqOlice8rumL9OLMmRG3ObSzLV++2ETgBe +xpEawSJKj7UpCpw2EJtMFvSPXrHIMhkN4rUkh1Pzoo7+i4/MVIoDPljPgxPOtFNS +tECA/3kD2DlkIY/wOlkF8T1lg7A8Q92aVXiyIHmXubrHdT4bhr4YRbyvltEB2eA+ +z4LLyqz+kMKHN1TYhMJUGur/C/Le3sNrhF2veqOCdPBomTwpWwJ4PPmN0kqeT0N3 +D1CJVrt4Uj8W9N7fPsguYAehs5e06MCcAT3Dl1EqNNEJw/elAgMBAAGjggJ9MIIC +eTAfBgNVHREEGDAWghRsb2NhbGhvc3QuZGFwbGllLmNvbTAJBgNVHRMEAjAAMCsG +A1UdHwQkMCIwIKAeoByGGmh0dHA6Ly9ncC5zeW1jYi5jb20vZ3AuY3JsMG8GA1Ud +IARoMGYwZAYGZ4EMAQIBMFowKgYIKwYBBQUHAgEWHmh0dHBzOi8vd3d3LnJhcGlk +c3NsLmNvbS9sZWdhbDAsBggrBgEFBQcCAjAgDB5odHRwczovL3d3dy5yYXBpZHNz +bC5jb20vbGVnYWwwHwYDVR0jBBgwFoAUl8InUJ7CyewMiDLIfK3ipgFP2m8wDgYD +VR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBXBggr +BgEFBQcBAQRLMEkwHwYIKwYBBQUHMAGGE2h0dHA6Ly9ncC5zeW1jZC5jb20wJgYI +KwYBBQUHMAKGGmh0dHA6Ly9ncC5zeW1jYi5jb20vZ3AuY3J0MIIBAgYKKwYBBAHW +eQIEAgSB8wSB8ADuAHYA3esdK3oNT6Ygi4GtgWhwfi6OnQHVXIiNPRHEzbbsvswA +AAFVOonOzQAABAMARzBFAiEAzh4K7ZOSGCCFFvzAvrfl+o5AKcnmV7NHPgQZe3x4 +hZgCIH/M2LZI1OSdkQbF2wgD/xH4PvQ4i8TTOdGB0WAYVr1eAHQApLkJkLQYWBSH +uxOizGdwCjw1mAT5G9+443fNDsgN3BAAAAFVOonO8gAABAMARTBDAh84cfLQthSR +Pe6hFgL8TPSuCUxIFBcEbnIPNB7ZxQwYAiBTClbmIn81bBkwAjasJu2u+UdxGE0i +Wx5lFe5X9pqsUTANBgkqhkiG9w0BAQsFAAOCAQEAAWYuT/fTBZdXb4kwoVaUnc82 +2CEnGuOHr9QMdGRMqWJRe068StADdw1u3V6bcB7+mBiGl8C+WOLhv9WxYKqNFvyj +Eeaeekb4GqfrfuxNvoOU/vHdYaww2J9N1ESgIV4BdFF8aNgOnjpRcKSMsMgzNJdU +lh6l7jhnTeNYCyMnn+2dVQBcRQvptKmpkS4sK6NAVSMWDioImEoGj0PCdLqG8k21 +d3vNddCEQmcNUTHs38nswUKZxfQKpjo+z9jBFmurmaNqSFnd8ySmBELZjXEOXEQz +KBlUSDj3UYVmH49t0toGyHVfKHPCBLyUZhvUTy0tNVgn9Nc+/MXJnv+c5rxVeQ== +-----END CERTIFICATE----- diff --git a/express-server/node_modules/certpem/index.js b/express-server/node_modules/certpem/index.js new file mode 100644 index 00000000..376f3bac --- /dev/null +++ b/express-server/node_modules/certpem/index.js @@ -0,0 +1,120 @@ +'use strict'; + +var certInfo = module.exports; +module.exports.certpem = certInfo; + +// ES5 version of mergeDeep +// https://stackoverflow.com/questions/27936772/how-to-deep-merge-instead-of-shallow-merge +/** + * Simple object check. + * @param item + * @returns {boolean} + */ +function isObject(item) { + return (item && typeof item === 'object' && !Array.isArray(item)); +} + +/** + * Deep merge two objects. + * @param target + * @param ...sources + */ +function merge(target) { + var sources = Array.prototype.slice.call(arguments); + sources.shift(); + if (!sources.length) { return target; } + var source = sources.shift(); + var obj; + + if (isObject(target) && isObject(source)) { + Object.keys(source).forEach(function (key) { + if (isObject(source[key])) { + if (!target[key]) { obj = {}; obj[key] = {}; Object.assign(target, obj); } + merge(target[key], source[key]); + } else { + obj = {}; obj[key] = source[key]; + Object.assign(target, obj); + } + }); + } + + sources.unshift(target); + return merge.apply(null, sources); +} + +var common = require("asn1js/org/pkijs/common"); +var _asn1js = require("asn1js"); +var _pkijs = require("pkijs"); +var _x509schema = require("pkijs/org/pkijs/x509_schema"); + +// #region Merging function/object declarations for ASN1js and PKIjs +var asn1js = merge(_asn1js, common); + +var x509schema = merge(_x509schema, asn1js); + +var pkijs_1 = merge(_pkijs, asn1js); +var pkijs = merge(pkijs_1, x509schema); + +// this is really memory expensive to do +// (about half of a megabyte of loaded code) +certInfo._pemToBinAb = function (pem) { + var b64 = pem.replace(/(-----(BEGIN|END) CERTIFICATE-----|[\n\r])/g, ''); + var buf = Buffer.from(b64, 'base64'); + var ab = new Uint8Array(buf).buffer; // WORKS + //var ab = buf.buffer // Doesn't work + + return ab; +}; +certInfo.debug = certInfo.getCertInfo = function (pem) { + var ab = module.exports._pemToBinAb(pem); + + var asn1 = pkijs.org.pkijs.fromBER(ab); + var certSimpl = new pkijs.org.pkijs.simpl.CERT({ schema: asn1.result }); + + return certSimpl; +}; + +certInfo.info = certInfo.getBasicInfo = function (pem) { + var c = certInfo.getCertInfo(pem); + var domains = []; + var sub; + + c.extensions.forEach(function (ext) { + if (ext.parsedValue && ext.parsedValue.altNames) { + ext.parsedValue.altNames.forEach(function (alt) { + domains.push(alt.Name); + }); + } + }); + + sub = c.subject.types_and_values[0].value.value_block.value || null; + + return { + subject: sub + , altnames: domains + // for debugging during console.log + // do not expect these values to be here + , _issuedAt: c.notBefore.value + , _expiresAt: c.notAfter.value + , issuedAt: new Date(c.notBefore.value).valueOf() + , expiresAt: new Date(c.notAfter.value).valueOf() + }; +}; + +certInfo.getCertInfoFromFile = function (pemFile) { + return require('fs').readFileSync(pemFile, 'ascii'); +}; + +/* +certInfo.testGetCertInfo = function (pathname) { + var path = require('path'); + var pemFile = pathname || path.join(__dirname, '..', 'tests', 'example.cert.pem'); + return certInfo.getCertInfo(certInfo.getCertInfoFromFile(pemFile)); +}; + +certInfo.testBasicCertInfo = function (pathname) { + var path = require('path'); + var pemFile = pathname || path.join(__dirname, '..', 'tests', 'example.cert.pem'); + return certInfo.getBasicInfo(certInfo.getCertInfoFromFile(pemFile)); +}; +*/ diff --git a/express-server/node_modules/certpem/package.json b/express-server/node_modules/certpem/package.json new file mode 100644 index 00000000..206b22df --- /dev/null +++ b/express-server/node_modules/certpem/package.json @@ -0,0 +1,105 @@ +{ + "_args": [ + [ + "certpem@^1.1.0", + "/nodeapps/https-test/greenlock-express.js/node_modules/greenlock" + ] + ], + "_from": "certpem@>=1.1.0 <2.0.0", + "_id": "certpem@1.1.2", + "_inCache": true, + "_installable": true, + "_location": "/certpem", + "_nodeVersion": "10.6.0", + "_npmOperationalInternal": { + "host": "s3://npm-registry-packages", + "tmp": "tmp/certpem_1.1.2_1534472297185_0.6089090318511978" + }, + "_npmUser": { + "email": "coolaj86@gmail.com", + "name": "coolaj86" + }, + "_npmVersion": "6.1.0", + "_phantomChildren": {}, + "_requested": { + "name": "certpem", + "raw": "certpem@^1.1.0", + "rawSpec": "^1.1.0", + "scope": null, + "spec": ">=1.1.0 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/greenlock" + ], + "_resolved": "https://registry.npmjs.org/certpem/-/certpem-1.1.2.tgz", + "_shasum": "b532a03e9be59dcfe99c0350aff21d6bbbb4b83d", + "_shrinkwrap": null, + "_spec": "certpem@^1.1.0", + "_where": "/nodeapps/https-test/greenlock-express.js/node_modules/greenlock", + "author": { + "email": "coolaj86@gmail.com", + "name": "AJ ONeal", + "url": "https://coolaj86.com/" + }, + "bin": { + "certpem": "bin/certpem.js" + }, + "bugs": { + "url": "https://git.coolaj86.com/coolaj86/cert-info.js/issues" + }, + "dependencies": { + "asn1js": "^1.2.12", + "pkijs": "^1.3.27" + }, + "description": "Read basic info (subject, altnames, expiresAt, issuedAt) from a cert.pem / x509 certificate (tls / ssl / https) ", + "devDependencies": {}, + "directories": {}, + "dist": { + "fileCount": 7, + "integrity": "sha512-rqddNO1OdN6o7j1C486Os9USHgGEyoBSRHDgVAqx0jVAmGlgGQ1XPCrrl2KKxzdWBNC184V3gpV5BsvcDDQ+Vg==", + "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbdjBpCRA9TVsSAnZWagAA7y0P/ijpH77/RCiFiLVcZYbP\ne5ifxMsLDwRyORj6PDOyoHUTtz3Km7aBCmKl104pBp4R2LvE49zYge5IzGUB\nunpwAciLL06JnG9aOLPVJGR60Vk6i3no4dtbZxOzubMDiAnyaE5377uHnXLk\ni82+UZM056ZxVTnf8FMsSdE7PYpqitPy+jRHw0h9F8k4mo7V6RftuVImUJYW\nOknvSTsbMe/B+5MjUKWGx9hTIwBE/926P48x+VHnRMP+6yj2JWGKpllRueuc\ndLntSBXGUgtNGVkG0Q4uZ4VM+hm1BYUinu6BNKy7999JH+QChK3HqpSuy3dw\nbYkfdRAFAVquk12r668kFT7I5F7zAsqrjL8rbZ/3bwR5fstqSrJ3W98EMbLK\nzYQ33pm4UiDfXmT33gXW+pWWbP+4V5eNfz9JqEET5xxlluqnPNqJzhK0J4dY\nImSg5lu0VO5n1wkCcwA5txwH5RyTTTQ8cvS+yj82+IL9n6QXkFr4tpBX08Ug\nF7N8Vx+u6NIZWOhkApL04BW6PmlOcRk6hfCJ8S+5niUe3Tew1odbuo2ayzYV\nSZakVRx1JPsDe4Jpjaz0xTtnudkRzVENg+HGiWlflOuC+DEjpER1Y6uN5j66\nmGSBx1NRcJ4P/Vc8zVPUNMpN3MD37zRXoh0JUQdcGUtucT6zBCX1JZvMlHO+\nhBsN\r\n=c78a\r\n-----END PGP SIGNATURE-----\r\n", + "shasum": "b532a03e9be59dcfe99c0350aff21d6bbbb4b83d", + "tarball": "https://registry.npmjs.org/certpem/-/certpem-1.1.2.tgz", + "unpackedSize": 9695 + }, + "gitHead": "1b62407ea523e9e58799ff0516eadeaeb34347f5", + "homepage": "https://git.coolaj86.com/coolaj86/cert-info.js", + "keywords": [ + "altnames", + "asn1", + "at", + "cert", + "cert.pem", + "certificate", + "expired", + "expires", + "expiresAt", + "issued", + "issuedAt", + "notAfter", + "notBefore", + "pki", + "subject", + "x509" + ], + "license": "(MIT OR Apache-2.0)", + "main": "index.js", + "maintainers": [ + { + "name": "coolaj86", + "email": "coolaj86@gmail.com" + } + ], + "name": "certpem", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "https://git.coolaj86.com/coolaj86/cert-info.js.git" + }, + "scripts": { + "test": "node test.js" + }, + "version": "1.1.2" +} diff --git a/express-server/node_modules/certpem/test.js b/express-server/node_modules/certpem/test.js new file mode 100644 index 00000000..20e788f1 --- /dev/null +++ b/express-server/node_modules/certpem/test.js @@ -0,0 +1,3 @@ +'use strict'; + +require('./bin/certpem.js'); diff --git a/express-server/node_modules/express-basic-auth/.circleci/config.yml b/express-server/node_modules/express-basic-auth/.circleci/config.yml new file mode 100644 index 00000000..24916275 --- /dev/null +++ b/express-server/node_modules/express-basic-auth/.circleci/config.yml @@ -0,0 +1,37 @@ +# Javascript Node CircleCI 2.0 configuration file +# +# Check https://circleci.com/docs/2.0/language-javascript/ for more details +# +version: 2 +jobs: + build: + docker: + # specify the version you desire here + - image: circleci/node:7.10 + + # Specify service dependencies here if necessary + # CircleCI maintains a library of pre-built images + # documented at https://circleci.com/docs/2.0/circleci-images/ + # - image: circleci/mongo:3.4.4 + + working_directory: ~/repo + + steps: + - checkout + + # Download and cache dependencies + - restore_cache: + keys: + - v1-dependencies-{{ checksum "package.json" }} + # fallback to using the latest cache if no exact match is found + - v1-dependencies- + + - run: npm install + + - save_cache: + paths: + - node_modules + key: v1-dependencies-{{ checksum "package.json" }} + + # run tests! + - run: npm test diff --git a/express-server/node_modules/express-basic-auth/README.md b/express-server/node_modules/express-basic-auth/README.md new file mode 100644 index 00000000..c61ee59d --- /dev/null +++ b/express-server/node_modules/express-basic-auth/README.md @@ -0,0 +1,205 @@ +# express-basic-auth + +[![npm version](https://badge.fury.io/js/express-basic-auth.svg)](https://badge.fury.io/js/express-basic-auth) +[![npm](https://img.shields.io/npm/dm/express-basic-auth.svg)]() +[![CircleCI](https://circleci.com/gh/LionC/express-basic-auth/tree/master.svg?style=shield&circle-token=74f7b1557100b45259e67d2492c263e4f99365d4)](https://circleci.com/gh/LionC/express-basic-auth/tree/master) +[![David](https://img.shields.io/david/strongloop/express.svg)]() +![TypeScript compatible](https://img.shields.io/badge/typescript-compatible-brightgreen.svg) +[![MIT Licence](https://badges.frapsoft.com/os/mit/mit.svg?v=103)](https://opensource.org/licenses/mit-license.php) + +Simple plug & play HTTP basic auth middleware for Express. + +## How to install + +Just run + +```shell +npm install express-basic-auth +``` + +## How to use + +The module will export a function, that you can call with an options object to +get the middleware: + +```js +const app = require('express')() +const basicAuth = require('express-basic-auth') + +app.use(basicAuth({ + users: { 'admin': 'supersecret' } +})) +``` + +The middleware will now check incoming requests to match the credentials +`admin:supersecret`. + +The middleware will check incoming requests for a basic auth (`Authorization`) +header, parse it and check if the credentials are legit. If there are any +credentials, an `auth` property will be added to the request, containing +an object with `user` and `password` properties, filled with the credentials, +no matter if they are legit or not. + +**If a request is found to not be authorized**, it will respond with HTTP 401 +and a configurable body (default empty). + +### Static Users + +If you simply want to check basic auth against one or multiple static credentials, +you can pass those credentials in the `users` option: + +```js +app.use(basicAuth({ + users: { + 'admin': 'supersecret', + 'adam': 'password1234', + 'eve': 'asdfghjkl', + } +})) +``` + +The middleware will check incoming requests to have a basic auth header matching +one of the three passed credentials. + +### Custom authorization + +Alternatively, you can pass your own `authorizer` function, to check the credentials +however you want. It will be called with a username and password and is expected to +return `true` or `false` to indicate that the credentials were approved or not: + +```js +app.use(basicAuth( { authorizer: myAuthorizer } )) + +function myAuthorizer(username, password) { + return username.startsWith('A') && password.startsWith('secret') +} +``` + +This will authorize all requests with credentials where the username begins with +`'A'` and the password begins with `'secret'`. In an actual application you would +likely look up some data instead ;-) + +### Custom Async Authorization + +Note that the `authorizer` function above is expected to be synchronous. This is +the default behavior, you can pass `authorizeAsync: true` in the options object to indicate +that your authorizer is asynchronous. In this case it will be passed a callback +as the third parameter, which is expected to be called by standard node convention +with an error and a boolean to indicate if the credentials have been approved or not. +Let's look at the same authorizer again, but this time asynchronous: + +```js +app.use(basicAuth({ + authorizer: myAsyncAuthorizer, + authorizeAsync: true, +})) + +function myAsyncAuthorizer(username, password, cb) { + if (username.startsWith('A') && password.startsWith('secret')) + return cb(null, true) + else + return cb(null, false) +} +``` + +### Unauthorized Response Body + +Per default, the response body for unauthorized responses will be empty. It can +be configured using the `unauthorizedResponse` option. You can either pass a +static response or a function that gets passed the express request object and is +expected to return the response body. If the response body is a string, it will +be used as-is, otherwise it will be sent as JSON: + +```js +app.use(basicAuth({ + users: { 'Foo': 'bar' }, + unauthorizedResponse: getUnauthorizedResponse +})) + +function getUnauthorizedResponse(req) { + return req.auth + ? ('Credentials ' + req.auth.user + ':' + req.auth.password + ' rejected') + : 'No credentials provided' +} +``` + +### Challenge + +Per default the middleware will not add a `WWW-Authenticate` challenge header to +responses of unauthorized requests. You can enable that by adding `challenge: true` +to the options object. This will cause most browsers to show a popup to enter +credentials on unauthorized responses. You can set the realm (the realm +identifies the system to authenticate against and can be used by clients to save +credentials) of the challenge by passing a static string or a function that gets +passed the request object and is expected to return the challenge: + +```js +app.use(basicAuth({ + users: { 'someuser': 'somepassword' }, + challenge: true, + realm: 'Imb4T3st4pp', +})) +``` + +## Try it + +The repository contains an `example.js` that you can run to play around and try +the middleware. To use it just put it somewhere (or leave it where it is), run + +```shell +npm install express express-basic-auth +node example.js +``` + +This will start a small express server listening at port 8080. Just look at the file, +try out the requests and play around with the options. + +## TypeScript usage + +A declaration file is bundled with the library. You don't have to install a `@types/` package. + +```typescript +import * as basicAuth from 'express-basic-auth' +``` + +:bulb: **Using `req.auth`** + +express-basic-auth sets `req.auth` to an object containing the authorized credentials like `{ user: 'admin', password: 'supersecret' }`. + +In order to use that `req.auth` property in TypeScript without an unknown property error, use covariance to downcast the request type: + +```typescript +app.use(basicAuth(options), (req: basicAuth.IBasicAuthedRequest, res, next) => { + res.end(`Welcome ${req.auth.user} (your password is ${req.auth.password})`) + next() +}) +``` + +:bulb: **A note about type inference on synchronous authorizers** + +Due to some TypeScript's type-system limitation, the arguments' type of the synchronous authorizers are not inferred. +For example, on an asynchronous authorizer, the three arguments are correctly inferred: + +```typescript +basicAuth({ + authorizeAsync: true, + authorizer: (user, password, authorize) => authorize(null, password == 'secret'), +}) +``` + +However, on a synchronous authorizer, you'll have to type the arguments yourself: + +```typescript +basicAuth({ + authorizer: (user: string, password: string) => (password == 'secret') +}) +``` + +## Tests + +The cases in the `example.js` are also used for automated testing. So if you want +to contribute or just make sure that the package still works, simply run: + +```shell +npm test +``` diff --git a/express-server/node_modules/express-basic-auth/example.js b/express-server/node_modules/express-basic-auth/example.js new file mode 100644 index 00000000..da6ee494 --- /dev/null +++ b/express-server/node_modules/express-basic-auth/example.js @@ -0,0 +1,132 @@ +const express = require('express') + +var app = express() + +const basicAuth = require('./index.js') + +/** +* express-basic-auth +* +* Example server. Just run in the same folder: +* +* npm install express express-basic-auth +* +* and then run this file with node ('node example.js') +* +* You can send GET requests to localhost:8080/async , /custom, /challenge or /static +* and see how it refuses or accepts your request matching the basic auth settings. +*/ + +//TODO: Implement some form of automatic testing against the example server + +//Requires basic auth with username 'Admin' and password 'secret1234' +var staticUserAuth = basicAuth({ + users: { + 'Admin': 'secret1234' + }, + challenge: false +}) + +//Uses a custom (synchronous) authorizer function +var customAuthorizerAuth = basicAuth({ + authorizer: myAuthorizer +}) + +//Same, but sends a basic auth challenge header when authorization fails +var challengeAuth = basicAuth({ + authorizer: myAuthorizer, + challenge: true +}) + +//Uses a custom asynchronous authorizer function +var asyncAuth = basicAuth({ + authorizer: myAsyncAuthorizer, + authorizeAsync: true +}) + +//Uses a custom response body function +var customBodyAuth = basicAuth({ + users: { 'Foo': 'bar' }, + unauthorizedResponse: getUnauthorizedResponse +}) + +//Uses a static response body +var staticBodyAuth = basicAuth({ + unauthorizedResponse: 'Haaaaaha' +}) + +//Uses a JSON response body +var jsonBodyAuth = basicAuth({ + unauthorizedResponse: { foo: 'bar' } +}) + +//Uses a custom realm +var realmAuth = basicAuth({ + challenge: true, + realm: 'test' +}) + +//Uses a custom realm function +var realmFunctionAuth = basicAuth({ + challenge: true, + realm: function (req) { + return 'bla' + } +}) + +app.get('/static', staticUserAuth, function(req, res) { + res.status(200).send('You passed') +}) + +app.get('/custom', customAuthorizerAuth, function(req, res) { + res.status(200).send('You passed') +}) + +app.get('/challenge', challengeAuth, function(req, res) { + res.status(200).send('You passed') +}) + +app.get('/async', asyncAuth, function(req, res) { + res.status(200).send('You passed') +}) + +app.get('/custombody', customBodyAuth, function(req, res) { + res.status(200).send('You passed') +}) + +app.get('/staticbody', staticBodyAuth, function(req, res) { + res.status(200).send('You passed') +}) + +app.get('/jsonbody', jsonBodyAuth, function(req, res) { + res.status(200).send('You passed') +}) + +app.get('/realm', realmAuth, function(req, res) { + res.status(200).send('You passed') +}) + +app.get('/realmfunction', realmFunctionAuth, function(req, res) { + res.status(200).send('You passed') +}) + +app.listen(8080, function() { + console.log("Listening!") +}) + +//Custom authorizer checking if the username starts with 'A' and the password with 'secret' +function myAuthorizer(username, password) { + return username.startsWith('A') && password.startsWith('secret') +} + +//Same but asynchronous +function myAsyncAuthorizer(username, password, cb) { + if(username.startsWith('A') && password.startsWith('secret')) + return cb(null, true) + else + return cb(null, false) +} + +function getUnauthorizedResponse(req) { + return req.auth ? ('Credentials ' + req.auth.user + ':' + req.auth.password + ' rejected') : 'No credentials provided' +} diff --git a/express-server/node_modules/express-basic-auth/express-basic-auth.d.ts b/express-server/node_modules/express-basic-auth/express-basic-auth.d.ts new file mode 100644 index 00000000..19441ef2 --- /dev/null +++ b/express-server/node_modules/express-basic-auth/express-basic-auth.d.ts @@ -0,0 +1,137 @@ +/// + +import { Request, RequestHandler } from 'express' + +/** + * This is the middleware builder. + * + * Example: + * const users = { alice: '1234', bob: 'correcthorsebatterystaple' } + * app.use(basicAuth({ users, challenge: true }), myHandler) + * + * @param options The middleware's options (at least 'users' or 'authorizer' are mandatory). + */ +declare function expressBasicAuth(options: expressBasicAuth.BasicAuthMiddlewareOptions): RequestHandler + +declare namespace expressBasicAuth { + /** + * The configuration you pass to the middleware can take three forms, either: + * - A map of static users ({ bob: 'pa$$w0rd', ... }) ; + * - An authorizer function + * - An asynchronous authorizer function + */ + export type BasicAuthMiddlewareOptions = IUsersOptions | (IAuthorizerOptions | IAsyncAuthorizerOptions) + + /** + * express-basic-auth patches the request object to set an `auth` property that lets you retrieve the authed user. + * + * Example (TypeScript): + * app.use(basicAuth({ ... }), (req: basicAuth.IBasicAuthedRequest, res, next) => { + * res.end(`Welcome ${req.auth.user} (your password is ${req.auth.password})`) + * next() + * }) + */ + export interface IBasicAuthedRequest extends Request { + auth: { user: string, password: string } + } + + type Authorizer = (username: string, password: string) => boolean + + type AsyncAuthorizerCallback = (err: any, authed?: boolean) => void + + type AsyncAuthorizer = (username: string, password: string, callback: AsyncAuthorizerCallback) => void + + type ValueOrFunction = T | ((req: IBasicAuthedRequest) => T) + + interface IBaseOptions { + /** + * Per default the middleware will not add a WWW-Authenticate challenge header to responses of unauthorized requests. + * You can enable that by setting this to true, causing most browsers to show a popup to enter credentials + * on unauthorized responses. + * + * @default false + */ + challenge?: boolean + + /** + * You can set the realm (the realm identifies the system to authenticate against and can be used by clients to + * save credentials) of the challenge by passing a string or a function that gets passed the request and is + * expected to return the realm. + * + * @default undefined + */ + realm?: ValueOrFunction + + /** + * Per default, the response body for unauthorized responses will be empty. + * It can be configured using the unauthorizedResponse option. You can either pass a static response or a + * function that gets passed the express request object and is expected to return the response body. + * If the response body is a string, it will be used as-is, otherwise it will be sent as JSON. + * + * @default '' + */ + unauthorizedResponse?: ValueOrFunction + } + + interface IUsersOptions extends IBaseOptions { + /** + * If you simply want to check basic auth against one or multiple static credentials, you can pass those + * credentials in the users option. + * + * Example: + * const users = { alice: '1234', bob: 'correcthorsebatterystaple' } + * app.use(basicAuth({ users, challenge: true }), myHandler) + */ + users: { [username: string]: string } + } + + interface IAuthorizerOptions extends IBaseOptions { + /** + * Set to true if your authorizer is asynchronous. + */ + authorizeAsync?: false + + /** + * You can pass your own authorizer function, to check the credentials however you want. + * It will be called with a username and password and is expected to return true or false to indicate that the + * credentials were approved or not: + * + * Example: + * app.use(basicAuth({ authorizer })) + * + * function myAuthorizer(username: string, password: string) { + * return username.startsWith('A') && password.startsWith('secret'); + * } + * + * This will authorize all requests with credentials where the username begins with 'A' and the password begins + * with 'secret'. In an actual application you would likely look up some data instead ;-) + */ + authorizer: Authorizer + } + + interface IAsyncAuthorizerOptions extends IBaseOptions { + /** + * Set it to true to use a asynchronous authorizer. + */ + authorizeAsync: true + + /** + * You can pass an asynchronous authorizer. It will be passed a callback as the third parameter, which is + * expected to be called by standard node convention with an error and a boolean to indicate if the credentials + * have been approved or not. + * + * Example: + * app.use(basicAuth({ authorizer, authorizeAsync: true })); + * + * function authorizer(username, password, authorize) { + * if(username.startsWith('A') && password.startsWith('secret')) + * return authorize(null, true) + * + * return authorize(null, false) + * } + */ + authorizer: AsyncAuthorizer + } +} + +export = expressBasicAuth diff --git a/express-server/node_modules/express-basic-auth/index.js b/express-server/node_modules/express-basic-auth/index.js new file mode 100644 index 00000000..ee087567 --- /dev/null +++ b/express-server/node_modules/express-basic-auth/index.js @@ -0,0 +1,82 @@ +const auth = require('basic-auth') +const assert = require('assert') + +function ensureFunction(option, defaultValue) { + if(option == undefined) + return function() { return defaultValue } + + if(typeof option != 'function') + return function() { return option } + + return option +} + +function buildMiddleware(options) { + var challenge = options.challenge != undefined ? !!options.challenge : false + var users = options.users || {} + var authorizer = options.authorizer || staticUsersAuthorizer + var isAsync = options.authorizeAsync != undefined ? !!options.authorizeAsync : false + var getResponseBody = ensureFunction(options.unauthorizedResponse, '') + var realm = ensureFunction(options.realm) + + assert(typeof users == 'object', 'Expected an object for the basic auth users, found ' + typeof users + ' instead') + assert(typeof authorizer == 'function', 'Expected a function for the basic auth authorizer, found ' + typeof authorizer + ' instead') + + function staticUsersAuthorizer(username, password) { + for(var i in users) + if(username == i && password == users[i]) + return true + + return false + } + + return function authMiddleware(req, res, next) { + var authentication = auth(req) + + if(!authentication) + return unauthorized() + + req.auth = { + user: authentication.name, + password: authentication.pass + } + + if(isAsync) + return authorizer(authentication.name, authentication.pass, authorizerCallback) + else if(!authorizer(authentication.name, authentication.pass)) + return unauthorized() + + return next() + + function unauthorized() { + if(challenge) { + var challengeString = 'Basic' + var realmName = realm(req) + + if(realmName) + challengeString += ' realm="' + realmName + '"' + + res.set('WWW-Authenticate', challengeString) + } + + //TODO: Allow response body to be JSON (maybe autodetect?) + const response = getResponseBody(req) + + if(typeof response == 'string') + return res.status(401).send(response) + + return res.status(401).json(response) + } + + function authorizerCallback(err, approved) { + assert.ifError(err) + + if(approved) + return next() + + return unauthorized() + } + } +} + +module.exports = buildMiddleware diff --git a/express-server/node_modules/express-basic-auth/package.json b/express-server/node_modules/express-basic-auth/package.json new file mode 100644 index 00000000..1dfadec5 --- /dev/null +++ b/express-server/node_modules/express-basic-auth/package.json @@ -0,0 +1,100 @@ +{ + "_args": [ + [ + "express-basic-auth@^1.1.5", + "/nodeapps/https-test/greenlock-express.js" + ] + ], + "_from": "express-basic-auth@>=1.1.5 <2.0.0", + "_hasShrinkwrap": false, + "_id": "express-basic-auth@1.1.6", + "_inCache": true, + "_installable": true, + "_location": "/express-basic-auth", + "_nodeVersion": "10.9.0", + "_npmOperationalInternal": { + "host": "s3://npm-registry-packages", + "tmp": "tmp/express-basic-auth_1.1.6_1540564508533_0.23608186033217282" + }, + "_npmUser": { + "email": "me@lionc.de", + "name": "lionc" + }, + "_npmVersion": "6.4.0", + "_phantomChildren": {}, + "_requested": { + "name": "express-basic-auth", + "raw": "express-basic-auth@^1.1.5", + "rawSpec": "^1.1.5", + "scope": null, + "spec": ">=1.1.5 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "#DEV:/" + ], + "_resolved": "https://registry.npmjs.org/express-basic-auth/-/express-basic-auth-1.1.6.tgz", + "_shasum": "a9d20e4d8da8f7212d4865f6006f9214c4b41a20", + "_shrinkwrap": null, + "_spec": "express-basic-auth@^1.1.5", + "_where": "/nodeapps/https-test/greenlock-express.js", + "author": { + "email": "me@lionc.de", + "name": "LionC" + }, + "bugs": { + "url": "https://github.com/LionC/express-basic-auth/issues" + }, + "dependencies": { + "basic-auth": "^2.0.1" + }, + "description": "Plug & play basic auth middleware for express", + "devDependencies": { + "@types/express": "^4.16.0", + "express": "^4.16.4", + "mocha": "^5.2.0", + "should": "^11.2.1", + "supertest": "^3.3.0", + "typescript": "^2.9.2" + }, + "directories": {}, + "dist": { + "fileCount": 7, + "integrity": "sha512-fRh/UU2q/YhvY0/Pkzi3VcLyjIExveW2NOOnOGgO6yO0jKXt6zcKPVPWSrL8nlhlh+YEH5LOjz+CGFML5dJQNw==", + "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb0yYdCRA9TVsSAnZWagAA/L0P/jGAALdYVv1Y7zpRb0b+\nCCvkxVYpxaVQ8bMc0cuT6I+EaZSa1xBe3ayUyoldeUoxfFfiaiD8giAWNkXq\nnDgvximSoZyxQkPVq2inVSFDSVAKYzliz9htBV6AfW64bd0SK2d1wV7TZhZE\njnF6blWFtuNM/8pnqmfIOZKD3HywRnriURqSXpHgcU6foemlyDv3ak8FMnVj\nuJCl30wxX2nAU+lD4Cmzv8bohVP5+DORRqVcfTnhaXSUyV3QhPNkN+PC7ffe\nYbKTxs1wjnYDvv1nbisrD+kWyvnfF0EUBMRzpTHdWvrlq+R8r5On1db1ECK3\nlL3BfFPZb7hH6Y6YNRWljDwtjomhvDjn6AMTARZi1V59KJkGLDFIWWT8VrJb\n684pJprANpG4sj5ZIAILR5MY+HK/R494beU/IV7Up1TXspINmk59ebjkIl7Q\nD4kxJHukML5eLtDNynWaOGZx048v1ePQb0GqqBew2TXvhiBi316sfUdf0HaS\n/L+DjdVLiZKdx6upod1dybgx6uDssUa08ZLIrTl9HBrTsZd59FjBQM7pbt5I\n3THzfGIp3UhCxuq/b3B9khbW4IHllglxLAwjiiKp8TAJN/RbC71xbzRPqvtM\nIfOT9c8rfeiVe4cjvPb6uTfB6wGP35fH+PDupoxtfPa86Jdun+3N6vywqkt1\n5vHK\r\n=dEdE\r\n-----END PGP SIGNATURE-----\r\n", + "shasum": "a9d20e4d8da8f7212d4865f6006f9214c4b41a20", + "tarball": "https://registry.npmjs.org/express-basic-auth/-/express-basic-auth-1.1.6.tgz", + "unpackedSize": 27326 + }, + "gitHead": "1ea015d2c6942b5d170cec6ce6e1a32a7c042100", + "homepage": "https://github.com/LionC/express-basic-auth#readme", + "keywords": [ + "auth", + "authentication", + "basic", + "express", + "http", + "middleware" + ], + "license": "MIT", + "main": "index.js", + "maintainers": [ + { + "name": "lionc", + "email": "me@lionc.de" + } + ], + "name": "express-basic-auth", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/LionC/express-basic-auth.git" + }, + "scripts": { + "check-dts": "tsc express-basic-auth.d.ts", + "test": "mocha test.js && npm run check-dts" + }, + "types": "express-basic-auth.d.ts", + "version": "1.1.6" +} diff --git a/express-server/node_modules/express-basic-auth/test.js b/express-server/node_modules/express-basic-auth/test.js new file mode 100644 index 00000000..9bf122ac --- /dev/null +++ b/express-server/node_modules/express-basic-auth/test.js @@ -0,0 +1,256 @@ +const should = require('should') +const basicAuth = require('./index.js') +const express = require('express') +const supertest = require('supertest'); + +var app = express() + +//Requires basic auth with username 'Admin' and password 'secret1234' +var staticUserAuth = basicAuth({ + users: { + 'Admin': 'secret1234' + }, + challenge: false +}) + +//Uses a custom (synchronous) authorizer function +var customAuthorizerAuth = basicAuth({ + authorizer: myAuthorizer +}) + +//Same, but sends a basic auth challenge header when authorization fails +var challengeAuth = basicAuth({ + authorizer: myAuthorizer, + challenge: true +}) + +//Uses a custom asynchronous authorizer function +var asyncAuth = basicAuth({ + authorizer: myAsyncAuthorizer, + authorizeAsync: true +}) + +//Uses a custom response body function +var customBodyAuth = basicAuth({ + users: { 'Foo': 'bar' }, + unauthorizedResponse: getUnauthorizedResponse +}) + +//Uses a static response body +var staticBodyAuth = basicAuth({ + unauthorizedResponse: 'Haaaaaha' +}) + +//Uses a JSON response body +var jsonBodyAuth = basicAuth({ + unauthorizedResponse: { foo: 'bar' } +}) + +//Uses a custom realm +var realmAuth = basicAuth({ + challenge: true, + realm: 'test' +}) + +//Uses a custom realm function +var realmFunctionAuth = basicAuth({ + challenge: true, + realm: function (req) { + return 'bla' + } +}) + +app.get('/static', staticUserAuth, function(req, res) { + res.status(200).send('You passed') +}) + +app.get('/custom', customAuthorizerAuth, function(req, res) { + res.status(200).send('You passed') +}) + +app.get('/challenge', challengeAuth, function(req, res) { + res.status(200).send('You passed') +}) + +app.get('/async', asyncAuth, function(req, res) { + res.status(200).send('You passed') +}) + +app.get('/custombody', customBodyAuth, function(req, res) { + res.status(200).send('You passed') +}) + +app.get('/staticbody', staticBodyAuth, function(req, res) { + res.status(200).send('You passed') +}) + +app.get('/jsonbody', jsonBodyAuth, function(req, res) { + res.status(200).send('You passed') +}) + +app.get('/realm', realmAuth, function(req, res) { + res.status(200).send('You passed') +}) + +app.get('/realmfunction', realmFunctionAuth, function(req, res) { + res.status(200).send('You passed') +}) + +//Custom authorizer checking if the username starts with 'A' and the password with 'secret' +function myAuthorizer(username, password) { + return username.startsWith('A') && password.startsWith('secret') +} + +//Same but asynchronous +function myAsyncAuthorizer(username, password, cb) { + if(username.startsWith('A') && password.startsWith('secret')) + return cb(null, true) + else + return cb(null, false) +} + +function getUnauthorizedResponse(req) { + return req.auth ? ('Credentials ' + req.auth.user + ':' + req.auth.password + ' rejected') : 'No credentials provided' +} + +describe('express-basic-auth', function() { + describe('static users', function() { + const endpoint = '/static' + + it('should reject on missing header', function(done) { + supertest(app) + .get(endpoint) + .expect(401, done) + }) + + it('should reject on wrong credentials', function(done) { + supertest(app) + .get(endpoint) + .auth('dude', 'stuff') + .expect(401, done) + }) + + it('should reject without challenge', function(done) { + supertest(app) + .get(endpoint) + .auth('dude', 'stuff') + .expect(function (res) { + if(res.headers['WWW-Authenticate']) + throw new Error('Response should not have a challenge') + }) + .expect(401, done) + }) + + it('should accept correct credentials', function(done) { + supertest(app) + .get(endpoint) + .auth('Admin', 'secret1234') + .expect(200, 'You passed', done) + }) + }) + + describe('custom authorizer', function() { + const endpoint = '/custom' + + it('should reject on missing header', function(done) { + supertest(app) + .get(endpoint) + .expect(401, done) + }) + + it('should reject on wrong credentials', function(done) { + supertest(app) + .get(endpoint) + .auth('dude', 'stuff') + .expect(401, done) + }) + + it('should accept fitting credentials', function(done) { + supertest(app) + .get(endpoint) + .auth('Aloha', 'secretverymuch') + .expect(200, 'You passed', done) + }) + }) + + describe('async authorizer', function() { + const endpoint = '/async' + + it('should reject on missing header', function(done) { + supertest(app) + .get(endpoint) + .expect(401, done) + }) + + it('should reject on wrong credentials', function(done) { + supertest(app) + .get(endpoint) + .auth('dude', 'stuff') + .expect(401, done) + }) + + it('should accept fitting credentials', function(done) { + supertest(app) + .get(endpoint) + .auth('Aererer', 'secretiveStuff') + .expect(200, 'You passed', done) + }) + }) + + describe('custom response body', function() { + it('should reject on missing header and generate resposne message', function(done) { + supertest(app) + .get('/custombody') + .expect(401, 'No credentials provided', done) + }) + + it('should reject on wrong credentials and generate response message', function(done) { + supertest(app) + .get('/custombody') + .auth('dude', 'stuff') + .expect(401, 'Credentials dude:stuff rejected', done) + }) + + it('should accept fitting credentials', function(done) { + supertest(app) + .get('/custombody') + .auth('Foo', 'bar') + .expect(200, 'You passed', done) + }) + + it('should reject and send static custom resposne message', function(done) { + supertest(app) + .get('/staticbody') + .expect(401, 'Haaaaaha', done) + }) + + it('should reject and send static custom json resposne message', function(done) { + supertest(app) + .get('/jsonbody') + .expect(401, { foo: 'bar' }, done) + }) + }) + + describe('challenge', function() { + it('should reject with blank challenge', function(done) { + supertest(app) + .get('/challenge') + .expect('WWW-Authenticate', 'Basic') + .expect(401, done) + }) + + it('should reject with custom realm challenge', function(done) { + supertest(app) + .get('/realm') + .expect('WWW-Authenticate', 'Basic realm="test"') + .expect(401, done) + }) + + it('should reject with custom generated realm challenge', function(done) { + supertest(app) + .get('/realmfunction') + .expect('WWW-Authenticate', 'Basic realm="bla"') + .expect(401, done) + }) + }) +}) diff --git a/express-server/node_modules/greenlock/LICENSE b/express-server/node_modules/greenlock/LICENSE new file mode 100644 index 00000000..b9ef4d36 --- /dev/null +++ b/express-server/node_modules/greenlock/LICENSE @@ -0,0 +1,41 @@ +Copyright 2017 AJ ONeal + +This is open source software; you can redistribute it and/or modify it under the +terms of either: + + a) the "MIT License" + b) the "Apache-2.0 License" + +MIT License + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + +Apache-2.0 License Summary + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/express-server/node_modules/greenlock/README.md b/express-server/node_modules/greenlock/README.md new file mode 100644 index 00000000..e7514bae --- /dev/null +++ b/express-server/node_modules/greenlock/README.md @@ -0,0 +1,567 @@ +!["Greenlock Logo"](https://git.coolaj86.com/coolaj86/greenlock.js/raw/branch/master/logo/greenlock-1063x250.png "Greenlock lock logo and work mark") + +!["Greenlock Function"](https://git.coolaj86.com/coolaj86/greenlock.js/raw/branch/master/logo/from-not-secure-to-secure-url-bar.png "from url bar showing not secure to url bar showing secure") + +Greenlock™ for node.js +===== + +Greenlock provides Free SSL, Free Wildcard SSL, and Fully Automated HTTPS
+certificates issued by Let's Encrypt v2 via [ACME](https://git.coolaj86.com/coolaj86/acme-v2.js) + +!["Lifetime Downloads"](https://img.shields.io/npm/dt/greenlock.svg "Lifetime Download Count can't be shown") +!["Monthly Downloads"](https://img.shields.io/npm/dm/greenlock.svg "Monthly Download Count can't be shown") +!["Weekly Downloads"](https://img.shields.io/npm/dw/greenlock.svg "Weekly Download Count can't be shown") +!["Stackoverflow Questions"](https://img.shields.io/stackexchange/stackoverflow/t/greenlock.svg "S.O. Question count can't be shown") + +| Sponsored by [ppl](https://ppl.family) | +Greenlock works +in the [Commandline](https://git.coolaj86.com/coolaj86/greenlock-cli.js) (cli), +as a [Web Server](https://git.coolaj86.com/coolaj86/greenlock-server.js), +in [Web Browsers](https://git.coolaj86.com/coolaj86/greenlock.html) (WebCrypto), +and with **node.js** ([npm](https://www.npmjs.com/package/greenlock)). + +Features +======== + + - [x] Actively Maintained and Supported + - [x] Automatic HTTPS + - [x] Free SSL + - [x] Free Wildcard SSL + - [x] Multiple domain support (up to 100 altnames per SAN) + - [x] Dynamic Virtual Hosting (vhost) + - [x] Automatical renewal (30 to 21 days before expiration) + - [x] Great ACME support via [acme.js](https://git.coolaj86.com/coolaj86/acme-v2.js) + - [x] "dry run" with self-diagnostics + - [x] ACME draft 12 + - [x] Let's Encrypt v2 + - [x] Let's Encrypt v1 + - [x] [Commandline](https://git.coolaj86.com/coolaj86/greenlock-cli.js) (cli) Utilities + - [x] Works with `bash`, `fish`, `zsh`, `cmd.exe`, `PowerShell`, and more + - [x] [Browser](https://git.coolaj86.com/coolaj86/greenlock.html) Support + - [x] Full node.js support, with modules for + - [x] [http/https](https://git.coolaj86.com/coolaj86/greenlock-express.js/src/branch/master/examples/https-server.js), [Express.js](https://git.coolaj86.com/coolaj86/greenlock-express.js), [cluster](https://git.coolaj86.com/coolaj86/greenlock-cluster.js), [hapi](https://git.coolaj86.com/coolaj86/greenlock-hapi.js), [Koa](https://git.coolaj86.com/coolaj86/greenlock-koa.js), [rill](https://git.coolaj86.com/coolaj86/greenlock-rill.js), [restify](https://git.coolaj86.com/coolaj86/greenlock-restify.js), spdy, etc + - [x] Great for securing your Raspberry Pi + - [x] Extensible Plugin Support + - [x] AWS S3, AWS Route53, Azure, CloudFlare, Consul, Digital Ocean, etcd, Redis + +Greenlock.js for Middleware +------ + +Documentation for using Greenlock with +[http/https](https://git.coolaj86.com/coolaj86/greenlock-express.js/src/branch/master/examples/https-server.js), +[Express.js](https://git.coolaj86.com/coolaj86/greenlock-express.js), +[cluster](https://git.coolaj86.com/coolaj86/greenlock-cluster.js), +[hapi](https://git.coolaj86.com/coolaj86/greenlock-hapi.js), +[Koa](https://git.coolaj86.com/coolaj86/greenlock-koa.js), +[rill](https://git.coolaj86.com/coolaj86/greenlock-rill.js). +[restify](https://git.coolaj86.com/coolaj86/greenlock-restify.js). + +Table of Contents +================= + + * Install + * **QuickStart** + * Simple Examples + * Example with ALL OPTIONS + * API + * Developer API + * Change History + * License + +Install +======= + +```bash +npm install --save greenlock@2.x +``` + +**Optional** dependency for *more efficient* RSA key generation: +(important for those on ARM devices like Raspberry Pi) +```bash +npm install --save ursa +``` + +**Optional** dependency for *Let's Encrypt v01* (pre-draft ACME spec) compatibility: +(important for those on ARM devices like Raspberry Pi) +```bash +npm install --save le-acme-core +``` + + +### Production vs Staging + +If at first you don't succeed, stop and switch to staging. + +I've implemented a "dry run" loopback test with self diagnostics +so it's pretty safe to start off with the production URLs +and be far less likely to hit the bad request rate limits. + +However, if your first attempt to get a certificate fails +I'd recommend switching to the staging acme server to debug - +unless you're very clear on what the failure was and how to fix it. + +``` +{ server: 'https://acme-staging-v02.api.letsencrypt.org/directory' } +``` + +### QuickStart Screencast + +Watch the QuickStart demonstration: [https://youtu.be/e8vaR4CEZ5s](https://youtu.be/e8vaR4CEZ5s&list=PLZaEVINf2Bq_lrS-OOzTUJB4q3HxarlXk) + +YouTube Video Preview + +* [0:00](https://www.youtube.com/watch?v=e8vaR4CEZ5s&list=PLZaEVINf2Bq_lrS-OOzTUJB4q3HxarlXk#t=0) - Intro +* [2:22](https://www.youtube.com/watch?v=e8vaR4CEZ5s&list=PLZaEVINf2Bq_lrS-OOzTUJB4q3HxarlXk#t=142) - Demonstrating QuickStart Example +* [6:37](https://www.youtube.com/watch?v=e8vaR4CEZ5s&list=PLZaEVINf2Bq_lrS-OOzTUJB4q3HxarlXk?t=397) - Troubleshooting / Gotchas + +#### Production Configuration (Part 2) + +* [1:00](https://www.youtube.com/watch?v=bTEn93gxY50&index=2&list=PLZaEVINf2Bq_lrS-OOzTUJB4q3HxarlXk&t=60) - Bringing Greenlock into an Existing Express Project +* [2:26](https://www.youtube.com/watch?v=bTEn93gxY50&index=2&list=PLZaEVINf2Bq_lrS-OOzTUJB4q3HxarlXk&t=146) - The `approveDomains` callback + +#### Security Concerns (Part 3) + +* [0:00](https://www.youtube.com/watch?v=aZgVqPzoZTY&index=3&list=PLZaEVINf2Bq_lrS-OOzTUJB4q3HxarlXk) - Potential Attacks, and Mitigation + + +Easy as 1, 2, 3... 4 +===== + +Greenlock is built to incredibly easy to use, without sacrificing customization or extensibility. + +The following examples range from just a few lines of code for getting started, +to more robust examples that you might start with for an enterprise-grade use of the ACME api. + +* Automatic HTTPS (for single sites) +* Fully Automatic HTTPS (for multi-domain vhosts) +* Manual HTTPS (for API integration) + +Automatic HTTPS +--------------- + +**Note**: For (fully) automatic HTTPS you may prefer +the [Express.js module](https://git.coolaj86.com/coolaj86/greenlock-express.js) + +This works for most people, but it's not as fun as some of the other examples. + +Great when + + - [x] You only need a limited number of certificates + - [x] You want to use the bare node http and https modules without fluff + +```js +//////////////////// +// INIT GREENLOCK // +//////////////////// + +var greenlock = require('greenlock').create({ + + version: 'draft-12' +, server: 'https://acme-v02.api.letsencrypt.org/directory' +, configDir: '~/.config/acme' + +, email: 'user@example.com' // IMPORTANT: Change email and domains +, agreeTos: true // Accept Let's Encrypt v2 Agreement +, communityMember: true // Get (rare) non-mandatory updates about cool greenlock-related stuff (default false) +, securityUpdates: true // Important and mandatory notices related to security or breaking API changes (default true) + +, approveDomains: approveDomains +}); +``` + +```js +///////////////////// +// APPROVE DOMAINS // +///////////////////// + + +function approveDomains(opts, certs, cb) { + + // check for domains you want to receive certificates for + if ('example.com' === opts.domain) { + cb(null, { options: opts, certs: certs }); + return; + } + + // return error otherwise + cb(new Error("bad domain")); +} +``` + +```js +//////////////////// +// CREATE SERVERS // +//////////////////// + +var redir = require('redirect-https')(); +require('http').createServer(greenlock.middleware(redir)).listen(80); + +require('spdy').createServer(greenlock.tlsOptions, function (req, res) { + res.end('Hello, Secure World!'); +}).listen(443); +``` + +Fully Automatic HTTPS +------------ + +**Note**: For (fully) automatic HTTPS you may prefer +the [Express.js module](https://git.coolaj86.com/coolaj86/greenlock-express.js) + +Great when + + - [x] You have a growing number of domains + - [x] You're integrating into your own hosting solution + - [x] Customize ACME http-01 or dns-01 challenge + +```js +//////////////////// +// INIT GREENLOCK // +//////////////////// + +var path = require('path'); +var os = require('os') +var Greenlock = require('greenlock'); + +var greenlock = Greenlock.create({ + version: 'draft-12' +, server: 'https://acme-v02.api.letsencrypt.org/directory' + + // approve a growing list of domains +, approveDomains: approveDomains + + // If you wish to replace the default account and domain key storage plugin +, store: require('le-store-certbot').create({ + configDir: path.join(os.homedir(), 'acme/etc') + , webrootPath: '/tmp/acme-challenges' + }) +}); + + +///////////////////// +// APPROVE DOMAINS // +///////////////////// + +var http01 = require('le-challenge-fs').create({ webrootPath: '/tmp/acme-challenges' }); +function approveDomains(opts, certs, cb) { + // This is where you check your database and associated + // email addresses with domains and agreements and such + + // Opt-in to submit stats and get important updates + opts.communityMember = true; + + // If you wish to replace the default challenge plugin, you may do so here + opts.challenges = { 'http-01': http01 }; + + // The domains being approved for the first time are listed in opts.domains + // Certs being renewed are listed in certs.altnames + if (certs) { + opts.domains = certs.altnames; + } + else { + opts.email = 'john.doe@example.com'; + opts.agreeTos = true; + } + + // NOTE: you can also change other options such as `challengeType` and `challenge` + // opts.challengeType = 'http-01'; + // opts.challenge = require('le-challenge-fs').create({}); + + cb(null, { options: opts, certs: certs }); +} + + +//////////////////// +// CREATE SERVERS // +//////////////////// + +var redir = require('redirect-https')(); +require('http').createServer(greenlock.middleware(redir)).listen(80); + +require('https').createServer(greenlock.tlsOptions, function (req, res) { + res.end('Hello, Secure World!'); +}).listen(443); +``` + +Manual HTTPS +------------- + +Here's a taste of the API that you might use if building a commandline tool or API integration +that doesn't use node's SNICallback. + +``` + + +///////////////////// +// SET USER PARAMS // +///////////////////// + +var opts = { + domains: [ 'example.com' // CHANGE EMAIL AND DOMAINS + , 'www.example.com' ] +, email: 'user@example.com' +, agreeTos: true // Accept Let's Encrypt v2 Agreement +, communityMember: true // Help make Greenlock better by submitting + // stats and getting updates +}; + + +//////////////////// +// INIT GREENLOCK // +//////////////////// + +var greenlock = require('greenlock').create({ + version: 'draft-12' +, server: 'https://acme-v02.api.letsencrypt.org/directory' +, configDir: '/tmp/acme/etc' +}); + + +/////////////////// +// GET TLS CERTS // +/////////////////// + +greenlock.register(opts).then(function (certs) { + console.log(certs); + // privkey, cert, chain, expiresAt, issuedAt, subject, altnames +}, function (err) { + console.error(err); +}); +``` + +The domain key and ssl certificates you get back can be used in a webserver like this: + +```js +var tlsOptions = { key: certs.privkey, cert: certs.cert + '\r\n' + certs.chain }; +require('https').createServer(tlsOptions, function (req, res) { + res.end('Hello, Secure World!'); +}).listen(443); +``` + +Example with ALL OPTIONS +========= + +The configuration consists of 3 components: + +* Storage Backend (search npm for projects starting with 'le-store-') +* ACME Challenge Handlers (search npm for projects starting with 'le-challenge-') +* Letsencryt Config (this is all you) + +```javascript +'use strict'; + +var Greenlock = require('greenlock'); +var greenlock; + + +// Storage Backend +var leStore = require('le-store-certbot').create({ + configDir: '~/acme/etc' // or /etc/letsencrypt or wherever +, debug: false +}); + + +// ACME Challenge Handlers +var leHttpChallenge = require('le-challenge-fs').create({ + webrootPath: '~/acme/var/' // or template string such as +, debug: false // '/srv/www/:hostname/.well-known/acme-challenge' +}); + + +function leAgree(opts, agreeCb) { + // opts = { email, domains, tosUrl } + agreeCb(null, opts.tosUrl); +} + +greenlock = Greenlock.create({ + version: 'draft-12' // 'draft-12' or 'v01' + // 'draft-12' is for Let's Encrypt v2 otherwise known as ACME draft 12 + // 'v02' is an alias for 'draft-12' + // 'v01' is for the pre-spec Let's Encrypt v1 + // + // staging API + //server: 'https://acme-staging-v02.api.letsencrypt.org/directory' + + // + // production API + server: 'https://acme-v02.api.letsencrypt.org/directory' + +, store: leStore // handles saving of config, accounts, and certificates +, challenges: { + 'http-01': leHttpChallenge // handles /.well-known/acme-challege keys and tokens + } +, challengeType: 'http-01' // default to this challenge type +, agreeToTerms: leAgree // hook to allow user to view and accept LE TOS +//, sni: require('le-sni-auto').create({}) // handles sni callback + + // renewals happen at a random time within this window +, renewWithin: 30 * 24 * 60 * 60 * 1000 // certificate renewal may begin at this time +, renewBy: 21 * 24 * 60 * 60 * 1000 // certificate renewal should happen by this time + +, debug: false +//, log: function (debug) {console.log.apply(console, args);} // handles debug outputs +}); + + +// If using express you should use the middleware +// app.use('/', greenlock.middleware()); +// +// Otherwise you should see the test file for usage of this: +// greenlock.challenges['http-01'].get(opts.domain, key, val, done) + + + +// Check in-memory cache of certificates for the named domain +greenlock.check({ domains: [ 'example.com' ] }).then(function (results) { + if (results) { + // we already have certificates + return; + } + + + // Register Certificate manually + greenlock.register({ + + domains: ['example.com'] // CHANGE TO YOUR DOMAIN (list for SANS) + , email: 'user@email.com' // CHANGE TO YOUR EMAIL + , agreeTos: '' // set to tosUrl string (or true) to pre-approve (and skip agreeToTerms) + , rsaKeySize: 2048 // 2048 or higher + , challengeType: 'http-01' // http-01, tls-sni-01, or dns-01 + + }).then(function (results) { + + console.log('success'); + + }, function (err) { + + // Note: you must either use greenlock.middleware() with express, + // manually use greenlock.challenges['http-01'].get(opts, domain, key, val, done) + // or have a webserver running and responding + // to /.well-known/acme-challenge at `webrootPath` + console.error('[Error]: node-greenlock/examples/standalone'); + console.error(err.stack); + + }); + +}); +``` + +Here's what `results` looks like: + +```javascript +{ privkey: '' // PEM encoded private key +, cert: '' // PEM encoded cert +, chain: '' // PEM encoded intermediate cert +, issuedAt: 0 // notBefore date (in ms) parsed from cert +, expiresAt: 0 // notAfter date (in ms) parsed from cert +, subject: '' // example.com +, altnames: [] // example.com,www.example.com +} +``` + +API +--- + +The full end-user API is exposed in the example above and includes all relevant options. + +``` +greenlock.register(opts) +greenlock.check(opts) +``` + +### Helper Functions + +We do expose a few helper functions: + +* Greenlock.validDomain(hostname) // returns '' or the hostname string if it's a valid ascii or punycode domain name + +TODO fetch domain tld list + +### Template Strings + +The following variables will be tempalted in any strings passed to the options object: + +* `~/` replaced with `os.homedir()` i.e. `/Users/aj` +* `:hostname` replaced with the first domain in the list i.e. `example.com` + +### Dangerous Options + +By default SNI is made to lowercase and is automatically rejected if it contains invalid characters for a domain. +This behavior can be modified: + + * `__dns_allow_dangerous_names` allow SNI names like "Robert'); DROP TABLE Students;" + * `__dns_preserve_case` passes SNI names such as "ExAMpLE.coM" without converting to lower case + +Developer API +------------- + +If you are developing an `le-store-*` or `le-challenge-*` plugin you need to be aware of +additional internal API expectations. + +**IMPORTANT**: + +Use `v2.0.0` as your initial version - NOT v0.1.0 and NOT v1.0.0 and NOT v3.0.0. +This is to indicate that your module is compatible with v2.x of node-greenlock. + +Since the public API for your module is defined by node-greenlock the major version +should be kept in sync. + +### store implementation + +See + +* getOptions() +* accounts. + * checkKeypair(opts, cb) + * check(opts, cb) + * setKeypair(opts, keypair, cb) + * set(opts, reg, cb) +* certificates. + * checkKeypair(opts, cb) + * check(opts, cb) + * setKeypair(opts, keypair, cb) + * set(opts, reg, cb) + +### challenge implementation + +See https://git.coolaj86.com/coolaj86/le-challenge-fs.js + +* `.set(opts, domain, key, value, cb);` // opts will be saved with domain/key +* `.get(opts, domain, key, cb);` // opts will be retrieved by domain/key +* `.remove(opts, domain, key, cb);` // opts will be retrieved by domain/key + +Change History +============== +* v2.4 + * v2.4.3 - add security updates (default true) independent of community updates (default false) +* v2.2 - Let's Encrypt v2 Support + * v2.2.11 - documentation updates + * v2.2.10 - don't let SNICallback swallow approveDomains errors 6286883fc2a6ebfff711a540a2e4d92f3ac2907c + * v2.2.8 - communityMember option support + * v2.2.7 - bugfix for wildcard support + * v2.2.5 - node v6.x compat + * v2.2.4 - don't promisify all of `dns` + * v2.2.3 - `renewWithin` default to 30 days + * v2.2.2 - replace git dependency with npm + * v2.2.1 - April 2018 **Let's Encrypt v2** support +* v2.1.17 - Nov 5th 2017 migrate back to personal repo +* v2.1.9 - Jan 18th 2017 renamed to greenlock +* v2.0.2 - Aug 9th 2016 update readme +* v2.0.1 - Aug 9th 2016 + * major refactor + * simplified API + * modular plugins + * knock out bugs +* v1.5.0 now using letiny-core v2.0.0 and rsa-compat +* v1.4.x I can't remember... but it's better! +* v1.1.0 Added letiny-core, removed node-letsencrypt-python +* v1.0.2 Works with node-letsencrypt-python +* v1.0.0 Thar be dragons + +LICENSE +======= + +Dual-licensed MIT and Apache-2.0 + +See LICENSE + +Greenlock™ is a trademark of AJ ONeal diff --git a/express-server/node_modules/greenlock/index.js b/express-server/node_modules/greenlock/index.js new file mode 100644 index 00000000..5e233d93 --- /dev/null +++ b/express-server/node_modules/greenlock/index.js @@ -0,0 +1,597 @@ +'use strict'; + +var DAY = 24 * 60 * 60 * 1000; +//var MIN = 60 * 1000; +var ACME = require('acme-v2/compat').ACME; +var pkg = require('./package.json'); +var PromiseA; +try { + PromiseA = require('bluebird'); +} catch(e) { + PromiseA = global.Promise; +} +var util = require('util'); +function promisifyAllSelf(obj) { + if (obj.__promisified) { return obj; } + Object.keys(obj).forEach(function (key) { + if ('function' === typeof obj[key]) { + obj[key + 'Async'] = util.promisify(obj[key]); + } + }); + obj.__promisified = true; + return obj; +} + +var Greenlock = module.exports; +Greenlock.Greenlock = Greenlock; +Greenlock.LE = Greenlock; +// in-process cache, shared between all instances +var ipc = {}; + +function _log(debug) { + if (debug) { + var args = Array.prototype.slice.call(arguments); + args.shift(); + args.unshift("[gl/index.js]"); + console.log.apply(console, args); + } +} + +Greenlock.defaults = { + productionServerUrl: 'https://acme-v01.api.letsencrypt.org/directory' +, stagingServerUrl: 'https://acme-staging.api.letsencrypt.org/directory' + +, rsaKeySize: ACME.rsaKeySize || 2048 +, challengeType: ACME.challengeType || 'http-01' +, challengeTypes: ACME.challengeTypes || [ 'http-01', 'dns-01' ] + +, acmeChallengePrefix: ACME.acmeChallengePrefix +}; + +// backwards compat +Object.keys(Greenlock.defaults).forEach(function (key) { + Greenlock[key] = Greenlock.defaults[key]; +}); + +// show all possible options +var u; // undefined +Greenlock._undefined = { + acme: u +, store: u +, challenge: u +, challenges: u +, sni: u +, tlsOptions: u + +, register: u +, check: u + +, renewWithin: u // le-auto-sni and core +//, renewBy: u // le-auto-sni +, acmeChallengePrefix: u +, rsaKeySize: u +, challengeType: u +, server: u +, version: u +, agreeToTerms: u +, _ipc: u +, duplicate: u +, _acmeUrls: u +}; +Greenlock._undefine = function (gl) { + Object.keys(Greenlock._undefined).forEach(function (key) { + if (!(key in gl)) { + gl[key] = u; + } + }); + + return gl; +}; +Greenlock.create = function (gl) { + gl.store = gl.store || require('le-store-certbot').create({ + debug: gl.debug + , configDir: gl.configDir + , logsDir: gl.logsDir + , webrootPath: gl.webrootPath + }); + gl.core = require('./lib/core'); + var log = gl.log || _log; + + if (!gl.challenges) { + gl.challenges = {}; + } + if (!gl.challenges['http-01']) { + gl.challenges['http-01'] = require('le-challenge-fs').create({ + debug: gl.debug + , webrootPath: gl.webrootPath + }); + } + if (!gl.challenges['dns-01']) { + try { + gl.challenges['dns-01'] = require('le-challenge-ddns').create({ debug: gl.debug }); + } catch(e) { + try { + gl.challenges['dns-01'] = require('le-challenge-dns').create({ debug: gl.debug }); + } catch(e) { + // not yet implemented + } + } + } + + gl = Greenlock._undefine(gl); + gl.acmeChallengePrefix = Greenlock.acmeChallengePrefix; + gl.rsaKeySize = gl.rsaKeySize || Greenlock.rsaKeySize; + gl.challengeType = gl.challengeType || Greenlock.challengeType; + gl._ipc = ipc; + gl._communityPackage = gl._communityPackage || 'greenlock.js'; + if ('greenlock.js' === gl._communityPackage) { + gl._communityPackageVersion = pkg.version; + } else { + gl._communityPackageVersion = gl._communityPackageVersion || ('greenlock.js-' + pkg.version); + } + gl.agreeToTerms = gl.agreeToTerms || function (args, agreeCb) { + agreeCb(new Error("'agreeToTerms' was not supplied to Greenlock and 'agreeTos' was not supplied to Greenlock.register")); + }; + + if (!gl.renewWithin) { gl.renewWithin = 30 * DAY; } + // renewBy has a default in le-sni-auto + + + + /////////////////////////// + // BEGIN VERSION MADNESS // + /////////////////////////// + + if (!gl.version) { + //console.warn("Please specify version: 'v01' (Let's Encrypt v1) or 'draft-12' (Let's Encrypt v2 / ACME draft 12)"); + console.warn(""); + console.warn(""); + console.warn(""); + console.warn("=========================================================="); + console.warn("== greenlock.js (v2.2.0+) =="); + console.warn("=========================================================="); + console.warn(""); + console.warn("Please specify 'version' option:"); + console.warn(""); + console.warn(" 'draft-12' for Let's Encrypt v2 and ACME draft 12"); + console.warn(" ('v02' is an alias of 'draft-12'"); + console.warn(""); + console.warn("or"); + console.warn(""); + console.warn(" 'v01' for Let's Encrypt v1 (deprecated)"); + console.warn(" (also 'npm install --save le-acme-core' as this legacy dependency will soon be removed)"); + console.warn(""); + console.warn("This will be required in versions v2.3+"); + console.warn(""); + console.warn(""); + } else if ('v02' === gl.version) { + gl.version = 'draft-11'; + } else if ('draft-12' === gl.version) { + gl.version = 'draft-11'; + } else if ('draft-11' === gl.version) { + // no-op + } else if ('v01' !== gl.version) { + throw new Error("Unrecognized version '" + gl.version + "'"); + } + + if (!gl.server) { + throw new Error("opts.server must specify an ACME directory URL, such as 'https://acme-staging-v02.api.letsencrypt.org/directory'"); + } + if ('staging' === gl.server || 'production' === gl.server) { + if ('staging' === gl.server) { + gl.server = 'https://acme-staging.api.letsencrypt.org/directory'; + gl.version = 'v01'; + gl._deprecatedServerName = 'staging'; + } + else if ('production' === gl.server) { + gl.server = 'https://acme-v01.api.letsencrypt.org/directory'; + gl.version = 'v01'; + gl._deprecatedServerName = 'production'; + } + console.warn(""); + console.warn(""); + console.warn("=== WARNING ==="); + console.warn(""); + console.warn("Due to versioning issues the '" + gl._deprecatedServerName + "' option is deprecated."); + console.warn("Please specify the full url and version."); + console.warn(""); + console.warn("For APIs add:"); + console.warn("\t, \"version\": \"" + gl.version + "\""); + console.warn("\t, \"server\": \"" + gl.server + "\""); + console.warn(""); + console.warn("For the CLI add:"); + console.warn("\t--acme-url '" + gl.server + "' \\"); + console.warn("\t--acme-version '" + gl.version + "' \\"); + console.warn(""); + console.warn(""); + } + + function loadLeV01() { + console.warn(""); + console.warn("=== WARNING ==="); + console.warn(""); + console.warn("Let's Encrypt v1 is deprecated."); + console.warn("Please update to Let's Encrypt v2 (ACME draft 12)"); + console.warn(""); + try { + return require('le-acme-core').ACME; + } catch(e) { + console.error(""); + console.error("=== Error (easy-to-fix) ==="); + console.error(""); + console.error("Hey, this isn't a big deal, but you need to manually add v1 support:"); + console.error(""); + console.error(" npm install --save le-acme-core"); + console.error(""); + console.error("Just run that real quick, restart, and everything will work great."); + console.error(""); + console.error(""); + process.exit(e.code || 13); + } + } + + if (-1 !== [ + 'https://acme-v02.api.letsencrypt.org/directory' + , 'https://acme-staging-v02.api.letsencrypt.org/directory' ].indexOf(gl.server) + ) { + if ('draft-11' !== gl.version) { + console.warn("Detected Let's Encrypt v02 URL. Changing version to draft-12."); + gl.version = 'draft-11'; + } + } else if (-1 !== [ + 'https://acme-v01.api.letsencrypt.org/directory' + , 'https://acme-staging.api.letsencrypt.org/directory' ].indexOf(gl.server) + || 'v01' === gl.version + ) { + if ('v01' !== gl.version) { + console.warn("Detected Let's Encrypt v01 URL (deprecated). Changing version to v01."); + gl.version = 'v01'; + } + } + if ('v01' === gl.version) { + ACME = loadLeV01(); + } + ///////////////////////// + // END VERSION MADNESS // + ///////////////////////// + + + + gl.acme = gl.acme || ACME.create({ debug: gl.debug }); + if (gl.acme.create) { + gl.acme = gl.acme.create(gl); + } + gl.acme = promisifyAllSelf(gl.acme); + gl._acmeOpts = gl.acme.getOptions(); + Object.keys(gl._acmeOpts).forEach(function (key) { + if (!(key in gl)) { + gl[key] = gl._acmeOpts[key]; + } + }); + + if (gl.store.create) { + gl.store = gl.store.create(gl); + } + gl.store = promisifyAllSelf(gl.store); + gl.store.accounts = promisifyAllSelf(gl.store.accounts); + gl.store.certificates = promisifyAllSelf(gl.store.certificates); + gl._storeOpts = gl.store.getOptions(); + Object.keys(gl._storeOpts).forEach(function (key) { + if (!(key in gl)) { + gl[key] = gl._storeOpts[key]; + } + }); + + + // + // Backwards compat for <= v2.1.7 + // + if (gl.challenge) { + console.warn("Deprecated use of gl.challenge. Use gl.challenges['" + Greenlock.challengeType + "'] instead."); + gl.challenges[gl.challengeType] = gl.challenge; + } + + Greenlock.challengeTypes.forEach(function (challengeType) { + var challenger = gl.challenges[challengeType]; + + if (!challenger) { + return; + } + + if (challenger.create) { + challenger = gl.challenges[challengeType] = challenger.create(gl); + } + if (!challenger.getOptionsAsync) { + challenger = gl.challenges[challengeType] = promisifyAllSelf(challenger); + } + gl['_challengeOpts_' + challengeType] = challenger.getOptions(); + Object.keys(gl['_challengeOpts_' + challengeType]).forEach(function (key) { + if (!(key in gl)) { + gl[key] = gl['_challengeOpts_' + challengeType][key]; + } + }); + + // TODO wrap these here and now with tplCopy? + if (!challenger.set || 5 !== challenger.set.length) { + throw new Error("gl.challenges[" + challengeType + "].set receives the wrong number of arguments." + + " You must define setChallenge as function (opts, domain, token, keyAuthorization, cb) { }"); + } + if (challenger.get && 4 !== challenger.get.length) { + throw new Error("gl.challenges[" + challengeType + "].get receives the wrong number of arguments." + + " You must define getChallenge as function (opts, domain, token, cb) { }"); + } + if (!challenger.remove || 4 !== challenger.remove.length) { + throw new Error("gl.challenges[" + challengeType + "].remove receives the wrong number of arguments." + + " You must define removeChallenge as function (opts, domain, token, cb) { }"); + } + +/* + if (!gl._challengeWarn && (!challenger.loopback || 4 !== challenger.loopback.length)) { + gl._challengeWarn = true; + console.warn("gl.challenges[" + challengeType + "].loopback should be defined as function (opts, domain, token, cb) { ... } and should prove (by external means) that the ACME server challenge '" + challengeType + "' will succeed"); + } + else if (!gl._challengeWarn && (!challenger.test || 5 !== challenger.test.length)) { + gl._challengeWarn = true; + console.warn("gl.challenges[" + challengeType + "].test should be defined as function (opts, domain, token, keyAuthorization, cb) { ... } and should prove (by external means) that the ACME server challenge '" + challengeType + "' will succeed"); + } +*/ + }); + + gl.sni = gl.sni || null; + gl.tlsOptions = gl.tlsOptions || gl.httpsOptions || {}; + + // Workaround for https://github.com/nodejs/node/issues/22389 + gl._updateServernames = function (cert) { + if (!gl._certnames) { gl._certnames = {}; } + + // Note: Any given domain could exist on multiple certs + // (especially during renewal where some may be added) + // hence we use a separate object for each domain and list each domain on it + // to get the minimal full set associated with each cert and domain + var allDomains = [cert.subject].concat(cert.altnames.slice(0)); + allDomains.forEach(function (name) { + name = name.toLowerCase(); + if (!gl._certnames[name]) { + gl._certnames[name] = {}; + } + allDomains.forEach(function (name2) { + name2 = name2.toLowerCase(); + gl._certnames[name][name2] = true; + }); + }); + }; + gl._checkServername = function (safeHost, servername) { + // odd, but acceptable + if (!safeHost || !servername) { return true; } + if (safeHost === servername) { return true; } + // connection established with servername and session is re-used for allowed name + if (gl._certnames[servername] && gl._certnames[servername][safeHost]) { + return true; + } + return false; + }; + + if (!gl.tlsOptions.SNICallback) { + if (!gl.getCertificatesAsync && !gl.getCertificates) { + if (Array.isArray(gl.approveDomains)) { + gl.approvedDomains = gl.approveDomains; + gl.approveDomains = null; + } + if (!gl.approveDomains) { + gl.approvedDomains = gl.approvedDomains || []; + gl.approveDomains = function (lexOpts, certs, cb) { + var err; + var emsg; + + if (!gl.email) { + throw new Error("le-sni-auto is not properly configured. Missing email"); + } + if (!gl.agreeTos) { + throw new Error("le-sni-auto is not properly configured. Missing agreeTos"); + } + if (!gl.approvedDomains.length) { + throw new Error("le-sni-auto is not properly configured. Missing approveDomains(domain, certs, callback)"); + } + if (lexOpts.domains.every(function (domain) { + return -1 !== gl.approvedDomains.indexOf(domain); + })) { + lexOpts.domains = gl.approvedDomains.slice(0); + lexOpts.email = gl.email; + lexOpts.agreeTos = gl.agreeTos; + lexOpts.communityMember = gl.communityMember; + lexOpts.telemetry = gl.telemetry; + return cb(null, { options: lexOpts, certs: certs }); + } + + emsg = "tls SNI for '" + lexOpts.domains.join(',') + "' rejected: not in list '" + gl.approvedDomains + "'"; + log(gl.debug, emsg, lexOpts.domains, gl.approvedDomains); + err = new Error(emsg); + err.code = 'E_REJECT_SNI'; + cb(err); + }; + } + + gl.getCertificates = function (domain, certs, cb) { + // certs come from current in-memory cache, not lookup + log(gl.debug, 'gl.getCertificates called for', domain, 'with certs for', certs && certs.altnames || 'NONE'); + var opts = { domain: domain, domains: certs && certs.altnames || [ domain ] }; + + try { + gl.approveDomains(opts, certs, function (_err, results) { + if (_err) { + if (false !== gl.logRejectedDomains) { + console.error("[Error] approveDomains rejected tls sni '" + domain + "'"); + console.error("[Error] (see https://git.coolaj86.com/coolaj86/greenlock.js/issues/11)"); + if ('E_REJECT_SNI' !== _err.code) { + console.error("[Error] This is the rejection message:"); + console.error(_err.message); + } + console.error(""); + } + cb(_err); + return; + } + + log(gl.debug, 'gl.approveDomains called with certs for', results.certs && results.certs.altnames || 'NONE', 'and options:'); + log(gl.debug, results.options); + + if (results.certs) { + log(gl.debug, 'gl renewing'); + return gl.core.certificates.renewAsync(results.options, results.certs).then( + function (certs) { + // Workaround for https://github.com/nodejs/node/issues/22389 + gl._updateServernames(certs); + cb(null, certs); + } + , function (e) { + console.debug("Error renewing certificate for '" + domain + "':"); + console.debug(e); + console.error(""); + cb(e); + } + ); + } + else { + log(gl.debug, 'gl getting from disk or registering new'); + return gl.core.certificates.getAsync(results.options).then( + function (certs) { + // Workaround for https://github.com/nodejs/node/issues/22389 + gl._updateServernames(certs); + cb(null, certs); + } + , function (e) { + console.debug("Error loading/registering certificate for '" + domain + "':"); + console.debug(e); + console.error(""); + cb(e); + } + ); + } + }); + } catch(e) { + console.error("[ERROR] Something went wrong in approveDomains:"); + console.error(e); + console.error("BUT WAIT! Good news: It's probably your fault, so you can probably fix it."); + } + }; + } + gl.sni = gl.sni || require('le-sni-auto'); + if (gl.sni.create) { + gl.sni = gl.sni.create(gl); + } + gl.tlsOptions.SNICallback = function (_domain, cb) { + // format and (lightly) sanitize sni so that users can be naive + // and not have to worry about SQL injection or fs discovery + var domain = (_domain||'').toLowerCase(); + // hostname labels allow a-z, 0-9, -, and are separated by dots + // _ is sometimes allowed + // REGEX // https://www.codeproject.com/Questions/1063023/alphanumeric-validation-javascript-without-regex + if (!gl.__sni_allow_dangerous_names && (!/^[a-z0-9_\.\-]+$/i.test(domain) || -1 !== domain.indexOf('..'))) { + log(gl.debug, "invalid sni '" + domain + "'"); + cb(new Error("invalid SNI")); + return; + } + + try { + gl.sni.sniCallback(gl.__sni_preserve_case && _domain || domain, cb); + } catch(e) { + console.error("[ERROR] Something went wrong in the SNICallback:"); + console.error(e); + cb(e); + } + }; + } + + // We want to move to using tlsOptions instead of httpsOptions, but we also need to make + // sure anything that uses this object will still work if looking for httpsOptions. + gl.httpsOptions = gl.tlsOptions; + + if (gl.core.create) { + gl.core = gl.core.create(gl); + } + + gl.renew = function (args, certs) { + return gl.core.certificates.renewAsync(args, certs); + }; + + gl.register = function (args) { + return gl.core.certificates.getAsync(args); + }; + + gl.check = function (args) { + // TODO must return email, domains, tos, pems + return gl.core.certificates.checkAsync(args); + }; + + gl.middleware = gl.middleware || require('./lib/middleware'); + if (gl.middleware.create) { + gl.middleware = gl.middleware.create(gl); + } + + //var SERVERNAME_RE = /^[a-z0-9\.\-_]+$/; + var SERVERNAME_G = /[^a-z0-9\.\-_]/; + gl.middleware.sanitizeHost = function (app) { + return function (req, res, next) { + function realNext() { + if ('function' === typeof app) { + app(req, res); + } else if ('function' === typeof next) { + next(); + } else { + res.statusCode = 500; + res.end("Error: no middleware assigned"); + } + } + // Get the host:port combo, if it exists + var host = (req.headers.host||'').split(':'); + + // if not, move along + if (!host[0]) { realNext(); return; } + + // if so, remove non-allowed characters + var safehost = host[0].toLowerCase().replace(SERVERNAME_G, ''); + + // if there were unallowed characters, complain + if (!gl.__sni_allow_dangerous_names && safehost.length !== host[0].length) { + res.statusCode = 400; + res.end("Malformed HTTP Header: 'Host: " + host[0] + "'"); + return; + } + + // make lowercase + if (!gl.__sni_preserve_case) { + host[0] = safehost; + req.headers.host = host.join(':'); + } + + // Note: This sanitize function is also called on plain sockets, which don't need Domain Fronting checks + if (req.socket.encrypted && !gl.__sni_allow_domain_fronting) { + if (req.socket && 'string' === typeof req.socket.servername) { + // Workaround for https://github.com/nodejs/node/issues/22389 + if (!gl._checkServername(safehost, req.socket.servername.toLowerCase())) { + res.statusCode = 400; + res.setHeader('Content-Type', 'text/html; charset=utf-8'); + res.end( + "

Domain Fronting Error

" + + "

This connection was secured using TLS/SSL for '" + req.socket.servername.toLowerCase() + "'

" + + "

The HTTP request specified 'Host: " + safehost + "', which is (obviously) different.

" + + "

Because this looks like a domain fronting attack, the connection has been terminated.

" + ); + return; + } + } else if (safehost && !gl.middleware.sanitizeHost._skip_fronting_check) { + // TODO how to handle wrapped sockets, as with telebit? + console.warn("\n\n\n[greenlock] WARN: no string for req.socket.servername," + + " skipping fronting check for '" + safehost + "'\n\n\n"); + gl.middleware.sanitizeHost._skip_fronting_check = true; + } + } + + // carry on + realNext(); + }; + }; + gl.middleware.sanitizeHost._skip_fronting_check = false; + + return gl; +}; diff --git a/express-server/node_modules/greenlock/lib/community.js b/express-server/node_modules/greenlock/lib/community.js new file mode 100644 index 00000000..e3c07c78 --- /dev/null +++ b/express-server/node_modules/greenlock/lib/community.js @@ -0,0 +1,51 @@ +'use strict'; + +function addCommunityMember(opts) { + // { name, version, email, domains, action, communityMember, telemetry } + setTimeout(function () { + var https = require('https'); + var req = https.request({ + hostname: 'api.ppl.family' + , port: 443 + , path: '/api/ppl.family/public/list' + , method: 'POST' + , headers: { + 'Content-Type': 'application/json' + } + }, function (err, resp) { + if (err) { return; } + resp.on('data', function () {}); + }); + var os = require('os'); + var data = { + address: opts.email + // greenlock-security is transactional and security only + , list: opts.communityMember ? (opts.name + '@ppl.family') : 'greenlock-security@ppl.family' + , action: opts.action // reg | renew + , package: opts.name + // hashed for privacy, but so we can still get some telemetry and inform users + // if abnormal things are happening (like several registrations for the same domain each day) + , domain: (opts.domains||[]).map(function (d) { + return require('crypto').createHash('sha1').update(d).digest('base64') + .replace(/\//g, '_').replace(/\+/g, '-').replace(/=/g, ''); + }).join(',') + }; + if (false !== opts.telemetry) { + data.arch = process.arch || os.arch(); + data.platform = process.platform || os.platform(); + data.release = os.release(); + data.version = opts.version; + data.node = process.version; + } + req.write(JSON.stringify(data, 2, null)); + req.end(); + }, 50); +} + +module.exports.add = addCommunityMember; + +if (require.main === module) { + //addCommunityMember('greenlock-express.js', 'reg', 'coolaj86+test42@gmail.com', ['coolaj86.com'], true); + //addCommunityMember('greenlock.js', 'reg', 'coolaj86+test37@gmail.com', ['oneal.im'], false); + //addCommunityMember('greenlock.js', 'reg', 'coolaj86+test11@gmail.com', ['ppl.family'], true); +} diff --git a/express-server/node_modules/greenlock/lib/core.js b/express-server/node_modules/greenlock/lib/core.js new file mode 100644 index 00000000..962cb1ba --- /dev/null +++ b/express-server/node_modules/greenlock/lib/core.js @@ -0,0 +1,459 @@ +'use strict'; + +var PromiseA; +try { + PromiseA = require('bluebird'); +} catch(e) { + PromiseA = global.Promise; +} +var util = require('util'); +function promisifyAll(obj) { + var aobj = {}; + Object.keys(obj).forEach(function (key) { + if ('function' === typeof obj[key]) { + aobj[key] = obj[key]; + aobj[key + 'Async'] = util.promisify(obj[key]); + } + }); + return aobj; +} + +function _log(debug) { + if (debug) { + var args = Array.prototype.slice.call(arguments); + args.shift(); + args.unshift("[greenlock/lib/core.js]"); + console.log.apply(console, args); + } +} + +module.exports.create = function (gl) { + var utils = require('./utils'); + var RSA = promisifyAll(require('rsa-compat').RSA); + var log = gl.log || _log; // allow custom log + var pendingRegistrations = {}; + + var core = { + // + // Helpers + // + getAcmeUrlsAsync: function (args) { + var now = Date.now(); + + // TODO check response header on request for cache time + if ((now - gl._ipc.acmeUrlsUpdatedAt) < 10 * 60 * 1000) { + return PromiseA.resolve(gl._ipc.acmeUrls); + } + + return gl.acme.getAcmeUrlsAsync(args.server).then(function (data) { + gl._ipc.acmeUrlsUpdatedAt = Date.now(); + gl._ipc.acmeUrls = data; + + return gl._ipc.acmeUrls; + }); + } + + + // + // The Main Enchilada + // + + // + // Accounts + // + , accounts: { + // Accounts + registerAsync: function (args) { + var err; + var copy = utils.merge(args, gl); + var disagreeTos; + args = utils.tplCopy(copy); + + disagreeTos = (!args.agreeTos && 'undefined' !== typeof args.agreeTos); + if (!args.email || disagreeTos || (parseInt(args.rsaKeySize, 10) < 2048)) { + err = new Error( + "In order to register an account both 'email' and 'agreeTos' must be present" + + " and 'rsaKeySize' must be 2048 or greater." + ); + err.code = 'E_ARGS'; + return PromiseA.reject(err); + } + + return utils.testEmail(args.email).then(function () { + var promise = gl.store.accounts.checkKeypairAsync(args).then(function (keypair) { + if (keypair) { + return RSA.import(keypair); + } + + if (args.accountKeypair) { + return gl.store.accounts.setKeypairAsync(args, RSA.import(args.accountKeypair)); + } + + var keypairOpts = { bitlen: args.rsaKeySize, exp: 65537, public: true, pem: true }; + return RSA.generateKeypairAsync(keypairOpts).then(function (keypair) { + keypair.privateKeyPem = RSA.exportPrivatePem(keypair); + keypair.publicKeyPem = RSA.exportPublicPem(keypair); + keypair.privateKeyJwk = RSA.exportPrivateJwk(keypair); + return gl.store.accounts.setKeypairAsync(args, keypair); + }); + }); + + return promise.then(function (keypair) { + // Note: the ACME urls are always fetched fresh on purpose + // TODO is this the right place for this? + return core.getAcmeUrlsAsync(args).then(function (urls) { + args._acmeUrls = urls; + + return gl.acme.registerNewAccountAsync({ + email: args.email + , newRegUrl: args._acmeUrls.newReg + , newAuthzUrl: args._acmeUrls.newAuthz + , agreeToTerms: function (tosUrl, agreeCb) { + if (true === args.agreeTos || tosUrl === args.agreeTos || tosUrl === gl.agreeToTerms) { + agreeCb(null, tosUrl); + return; + } + + // args.email = email; // already there + // args.domains = domains // already there + args.tosUrl = tosUrl; + gl.agreeToTerms(args, agreeCb); + } + , accountKeypair: keypair + + , debug: gl.debug || args.debug + }).then(function (receipt) { + var reg = { + keypair: keypair + , receipt: receipt + , email: args.email + , newRegUrl: args._acmeUrls.newReg + , newAuthzUrl: args._acmeUrls.newAuthz + }; + + // TODO move templating of arguments to right here? + return gl.store.accounts.setAsync(args, reg).then(function (account) { + // should now have account.id and account.accountId + args.account = account; + args.accountId = account.id; + return account; + }); + }); + }); + }); + }); + } + + // Accounts + , getAsync: function (args) { + return core.accounts.checkAsync(args).then(function (account) { + if (account) { + return account; + } else { + return core.accounts.registerAsync(args); + } + }); + } + + // Accounts + , checkAsync: function (args) { + var requiredArgs = ['accountId', 'email', 'domains', 'domain']; + if (!requiredArgs.some(function (key) { return -1 !== Object.keys(args).indexOf(key); })) { + return PromiseA.reject(new Error( + "In order to register or retrieve an account one of '" + requiredArgs.join("', '") + "' must be present" + )); + } + + var copy = utils.merge(args, gl); + args = utils.tplCopy(copy); + + return gl.store.accounts.checkAsync(args).then(function (account) { + + if (!account) { + return null; + } + + args.account = account; + args.accountId = account.id; + + return account; + }); + } + } + + , certificates: { + // Certificates + registerAsync: function (args) { + var err; + var challengeDefaults = gl['_challengeOpts_' + (args.challengeType || gl.challengeType)] || {}; + var copy = utils.merge(args, challengeDefaults || {}); + copy = utils.merge(copy, gl); + args = utils.tplCopy(copy); + + if (!Array.isArray(args.domains)) { + return PromiseA.reject(new Error('args.domains should be an array of domains')); + } + + if (!(args.domains.length && args.domains.every(utils.isValidDomain))) { + // NOTE: this library can't assume to handle the http loopback + // (or dns-01 validation may be used) + // so we do not check dns records or attempt a loopback here + err = new Error("invalid domain name(s): '" + args.domains + "'"); + err.code = "INVALID_DOMAIN"; + return PromiseA.reject(err); + } + + // If a previous request to (re)register a certificate is already underway we need + // to return the same promise created before rather than registering things twice. + // I'm not 100% sure how to properly handle the case where someone registers domain + // lists with some but not all elements common, nor am I sure that's even a case that + // is allowed to happen anyway. But for now we act like the list is completely the + // same if any elements are the same. + var promise; + args.domains.some(function (name) { + if (pendingRegistrations.hasOwnProperty(name)) { + promise = pendingRegistrations[name]; + return true; + } + }); + if (promise) { + return promise; + } + + promise = core.certificates._runRegistration(args); + + // Now that the registration is actually underway we need to make sure any subsequent + // registration attempts return the same promise until it is completed (but not after + // it is completed). + args.domains.forEach(function (name) { + pendingRegistrations[name] = promise; + }); + function clearPending() { + args.domains.forEach(function (name) { + delete pendingRegistrations[name]; + }); + } + promise.then(clearPending, clearPending); + + return promise; + } + , _runRegistration: function (args) { + // TODO renewal cb + // accountId and or email + return core.accounts.getAsync(args).then(function (account) { + args.account = account; + + var promise = gl.store.certificates.checkKeypairAsync(args).then(function (keypair) { + if (keypair) { + return RSA.import(keypair); + } + + if (args.domainKeypair) { + return gl.store.certificates.setKeypairAsync(args, RSA.import(args.domainKeypair)); + } + + var keypairOpts = { bitlen: args.rsaKeySize, exp: 65537, public: true, pem: true }; + return RSA.generateKeypairAsync(keypairOpts).then(function (keypair) { + keypair.privateKeyPem = RSA.exportPrivatePem(keypair); + keypair.publicKeyPem = RSA.exportPublicPem(keypair); + keypair.privateKeyJwk = RSA.exportPrivateJwk(keypair); + return gl.store.certificates.setKeypairAsync(args, keypair); + }); + }); + + return promise.then(function (domainKeypair) { + args.domainKeypair = domainKeypair; + //args.registration = domainKey; + + // Note: the ACME urls are always fetched fresh on purpose + // TODO is this the right place for this? + return core.getAcmeUrlsAsync(args).then(function (urls) { + args._acmeUrls = urls; + + var certReq = { + debug: args.debug || gl.debug + + , newAuthzUrl: args._acmeUrls.newAuthz + , newCertUrl: args._acmeUrls.newCert + + , accountKeypair: RSA.import(account.keypair) + , domainKeypair: domainKeypair + , domains: args.domains + , challengeType: args.challengeType + }; + + // + // IMPORTANT + // + // setChallenge and removeChallenge are handed defaults + // instead of args because getChallenge does not have + // access to args + // (args is per-request, defaults is per instance) + // + // Each of these fires individually for each domain, + // even though the certificate on the whole may have many domains + // + certReq.setChallenge = function (domain, key, value, done) { + log(args.debug, "setChallenge called for '" + domain + "'"); + var copy = utils.merge({ domains: [domain] }, args); + copy = utils.merge(copy, gl); + utils.tplCopy(copy); + + // TODO need to save challengeType + gl.challenges[args.challengeType].set(copy, domain, key, value, done); + }; + certReq.removeChallenge = function (domain, key, done) { + log(args.debug, "removeChallenge called for '" + domain + "'"); + var copy = utils.merge({ domains: [domain] }, gl); + utils.tplCopy(copy); + + gl.challenges[args.challengeType].remove(copy, domain, key, done); + }; + + log(args.debug, 'calling greenlock.acme.getCertificateAsync', certReq.domains); + + return gl.acme.getCertificateAsync(certReq).then(utils.attachCertInfo); + }); + }).then(function (results) { + // { cert, chain, privkey /*TODO, subject, altnames, issuedAt, expiresAt */ } + + // args.certs.privkey = RSA.exportPrivatePem(options.domainKeypair); + args.certs = results; + // args.pems is deprecated + args.pems = results; + return gl.store.certificates.setAsync(args).then(function () { + return results; + }); + }); + }); + } + // Certificates + , renewAsync: function (args, certs) { + var renewableAt = core.certificates._getRenewableAt(args, certs); + var err; + //var halfLife = (certs.expiresAt - certs.issuedAt) / 2; + //var renewable = (Date.now() - certs.issuedAt) > halfLife; + + log(args.debug, "(Renew) Expires At", new Date(certs.expiresAt).toISOString()); + log(args.debug, "(Renew) Renewable At", new Date(renewableAt).toISOString()); + + if (!args.duplicate && Date.now() < renewableAt) { + err = new Error( + "[ERROR] Certificate issued at '" + + new Date(certs.issuedAt).toISOString() + "' and expires at '" + + new Date(certs.expiresAt).toISOString() + "'. Ignoring renewal attempt until '" + + new Date(renewableAt).toISOString() + "'. Set { duplicate: true } to force." + ); + err.code = 'E_NOT_RENEWABLE'; + return PromiseA.reject(err); + } + + // Either the cert has entered its renewal period + // or we're forcing a refresh via 'dupliate: true' + log(args.debug, "Renewing!"); + + if (!args.domains || !args.domains.length) { + args.domains = args.servernames || [certs.subject].concat(certs.altnames); + } + + return core.certificates.registerAsync(args); + } + // Certificates + , _isRenewable: function (args, certs) { + var renewableAt = core.certificates._getRenewableAt(args, certs); + + log(args.debug, "Check Expires At", new Date(certs.expiresAt).toISOString()); + log(args.debug, "Check Renewable At", new Date(renewableAt).toISOString()); + + if (args.duplicate || Date.now() >= renewableAt) { + log(args.debug, "certificates are renewable"); + return true; + } + + return false; + } + , _getRenewableAt: function (args, certs) { + return certs.expiresAt - (args.renewWithin || gl.renewWithin); + } + , checkAsync: function (args) { + var copy = utils.merge(args, gl); + utils.tplCopy(copy); + + // returns pems + return gl.store.certificates.checkAsync(copy).then(function (cert) { + if (cert) { + log(args.debug, 'checkAsync found existing certificates'); + return utils.attachCertInfo(cert); + } + + log(args.debug, 'checkAsync failed to find certificates'); + return null; + }); + } + // Certificates + , getAsync: function (args) { + var copy = utils.merge(args, gl); + args = utils.tplCopy(copy); + + return core.certificates.checkAsync(args).then(function (certs) { + if (!certs) { + // There is no cert available + if (false !== args.securityUpdates && !args._communityMemberAdded) { + try { + // We will notify all greenlock users of mandatory and security updates + // We'll keep track of versions and os so we can make sure things work well + // { name, version, email, domains, action, communityMember, telemetry } + require('./community').add({ + name: args._communityPackage + , version: args._communityPackageVersion + , email: args.email + , domains: args.domains || args.servernames + , action: 'reg' + , communityMember: args.communityMember + , telemetry: args.telemetry + }); + } catch(e) { /* ignore */ } + args._communityMemberAdded = true; + } + return core.certificates.registerAsync(args); + } + + if (core.certificates._isRenewable(args, certs)) { + // it's time to renew the available cert + if (false !== args.securityUpdates && !args._communityMemberAdded) { + try { + // We will notify all greenlock users of mandatory and security updates + // We'll keep track of versions and os so we can make sure things work well + // { name, version, email, domains, action, communityMember, telemetry } + require('./community').add({ + name: args._communityPackage + , version: args._communityPackageVersion + , email: args.email + , domains: args.domains || args.servernames + , action: 'renew' + , communityMember: args.communityMember + , telemetry: args.telemetry + }); + } catch(e) { /* ignore */ } + args._communityMemberAdded = true; + } + certs.renewing = core.certificates.renewAsync(args, certs); + if (args.waitForRenewal) { + return certs.renewing; + } + } + + // return existing unexpired (although potentially stale) certificates when available + // there will be an additional .renewing property if the certs are being asynchronously renewed + return certs; + }).then(function (results) { + // returns pems + return results; + }); + } + } + + }; + + return core; +}; diff --git a/express-server/node_modules/greenlock/lib/middleware.js b/express-server/node_modules/greenlock/lib/middleware.js new file mode 100644 index 00000000..4309689e --- /dev/null +++ b/express-server/node_modules/greenlock/lib/middleware.js @@ -0,0 +1,68 @@ +'use strict'; + +var utils = require('./utils'); + +function _log(debug) { + if (debug) { + var args = Array.prototype.slice.call(arguments); + args.shift(); + args.unshift("[greenlock/lib/middleware.js]"); + console.log.apply(console, args); + } +} + +module.exports.create = function (gl) { + if (!gl.challenges['http-01'] || !gl.challenges['http-01'].get) { + throw new Error("middleware requires challenge plugin with get method"); + } + var log = gl.log || _log; + + log(gl.debug, "created middleware"); + return function (_app) { + if (_app && 'function' !== typeof _app) { + throw new Error("use greenlock.middleware() or greenlock.middleware(function (req, res) {})"); + } + var prefix = gl.acmeChallengePrefix || '/.well-known/acme-challenge/'; + + return function (req, res, next) { + if (0 !== req.url.indexOf(prefix)) { + log(gl.debug, "no match, skipping middleware"); + if ('function' === typeof _app) { + _app(req, res, next); + } + else if ('function' === typeof next) { + next(); + } + else { + res.statusCode = 500; + res.end("[500] Developer Error: app.use('/', greenlock.middleware()) or greenlock.middleware(app)"); + } + return; + } + + log(gl.debug, "this must be tinder, 'cuz it's a match!"); + + var token = req.url.slice(prefix.length); + var hostname = req.hostname || (req.headers.host || '').toLowerCase().replace(/:.*/, ''); + + log(gl.debug, "hostname", hostname, "token", token); + + var copy = utils.merge({ domains: [ hostname ] }, gl); + copy = utils.tplCopy(copy); + + // TODO tpl copy? + // TODO need to restore challengeType + gl.challenges['http-01'].get(copy, hostname, token, function (err, secret) { + if (err || !token) { + res.statusCode = 404; + res.setHeader('Content-Type', 'application/json; charset=utf-8'); + res.end('{ "error": { "message": "Error: These aren\'t the tokens you\'re looking for. Move along." } }'); + return; + } + + res.setHeader('Content-Type', 'text/plain; charset=utf-8'); + res.end(secret); + }); + }; + }; +}; diff --git a/express-server/node_modules/greenlock/lib/utils.js b/express-server/node_modules/greenlock/lib/utils.js new file mode 100644 index 00000000..a7223334 --- /dev/null +++ b/express-server/node_modules/greenlock/lib/utils.js @@ -0,0 +1,127 @@ +'use strict'; + +var path = require('path'); +var homeRe = new RegExp("^~(\\/|\\\\|\\" + path.sep + ")"); +// very basic check. Allows *.example.com. +var re = /^(\*\.)?[a-zA-Z0-9\.\-]+$/; +var punycode = require('punycode'); +var promisify = (require('util').promisify || require('bluebird').promisify); +var dnsResolveMxAsync = promisify(require('dns').resolveMx); + +module.exports.attachCertInfo = function (results) { + // XXX Note: Parsing the certificate info comes at a great cost (~500kb) + var getCertInfo = require('certpem').info; + var certInfo = getCertInfo(results.cert); + + // subject, altnames, issuedAt, expiresAt + Object.keys(certInfo).forEach(function (key) { + results[key] = certInfo[key]; + }); + + return results; +}; + +module.exports.isValidDomain = function (domain) { + if (re.test(domain)) { + return domain; + } + + domain = punycode.toASCII(domain); + + if (re.test(domain)) { + return domain; + } + + return ''; +}; + +module.exports.merge = function (/*defaults, args*/) { + var allDefaults = Array.prototype.slice.apply(arguments); + var args = allDefaults.shift(); + var copy = {}; + + allDefaults.forEach(function (defaults) { + Object.keys(defaults).forEach(function (key) { + copy[key] = defaults[key]; + }); + }); + + Object.keys(args).forEach(function (key) { + copy[key] = args[key]; + }); + + return copy; +}; + +module.exports.tplCopy = function (copy) { + var homedir = require('os').homedir(); + var tplKeys; + + copy.hostnameGet = function (copy) { + return (copy.domains || [])[0] || copy.domain; + }; + + Object.keys(copy).forEach(function (key) { + var newName; + if (!/Get$/.test(key)) { + return; + } + + newName = key.replace(/Get$/, ''); + copy[newName] = copy[newName] || copy[key](copy); + }); + + tplKeys = Object.keys(copy); + tplKeys.sort(function (a, b) { + return b.length - a.length; + }); + + tplKeys.forEach(function (key) { + if ('string' !== typeof copy[key]) { + return; + } + + copy[key] = copy[key].replace(homeRe, homedir + path.sep); + }); + + tplKeys.forEach(function (key) { + if ('string' !== typeof copy[key]) { + return; + } + + tplKeys.forEach(function (tplname) { + if (!copy[tplname]) { + // what can't be templated now may be templatable later + return; + } + copy[key] = copy[key].replace(':' + tplname, copy[tplname]); + }); + }); + + return copy; +}; + +module.exports.testEmail = function (email) { + var parts = (email||'').split('@'); + var err; + + if (2 !== parts.length || !parts[0] || !parts[1]) { + err = new Error("malformed email address '" + email + "'"); + err.code = 'E_EMAIL'; + return Promise.reject(err); + } + + return dnsResolveMxAsync(parts[1]).then(function (records) { + // records only returns when there is data + if (!records.length) { + throw new Error("sanity check fail: success, but no MX records returned"); + } + return email; + }, function (err) { + if ('ENODATA' === err.code) { + err = new Error("no MX records found for '" + parts[1] + "'"); + err.code = 'E_EMAIL'; + return Promise.reject(err); + } + }); +}; diff --git a/express-server/node_modules/greenlock/package.json b/express-server/node_modules/greenlock/package.json new file mode 100644 index 00000000..a12e0d21 --- /dev/null +++ b/express-server/node_modules/greenlock/package.json @@ -0,0 +1,124 @@ +{ + "_args": [ + [ + "greenlock@^2.4.9", + "/nodeapps/https-test/greenlock-express.js" + ] + ], + "_from": "greenlock@>=2.4.9 <3.0.0", + "_hasShrinkwrap": false, + "_id": "greenlock@2.4.10", + "_inCache": true, + "_installable": true, + "_location": "/greenlock", + "_nodeVersion": "10.13.0", + "_npmOperationalInternal": { + "host": "s3://npm-registry-packages", + "tmp": "tmp/greenlock_2.4.10_1541843287866_0.5046853213401128" + }, + "_npmUser": { + "email": "coolaj86@gmail.com", + "name": "coolaj86" + }, + "_npmVersion": "6.4.1", + "_phantomChildren": {}, + "_requested": { + "name": "greenlock", + "raw": "greenlock@^2.4.9", + "rawSpec": "^2.4.9", + "scope": null, + "spec": ">=2.4.9 <3.0.0", + "type": "range" + }, + "_requiredBy": [ + "/" + ], + "_resolved": "https://registry.npmjs.org/greenlock/-/greenlock-2.4.10.tgz", + "_shasum": "59a5878d76fba962aeec0b609b2a7a097a102261", + "_shrinkwrap": null, + "_spec": "greenlock@^2.4.9", + "_where": "/nodeapps/https-test/greenlock-express.js", + "author": { + "email": "coolaj86@gmail.com", + "name": "AJ ONeal", + "url": "https://coolaj86.com/" + }, + "bugs": { + "url": "https://git.coolaj86.com/coolaj86/greenlock.js/issues" + }, + "dependencies": { + "acme": "^1.0.6", + "acme-v2": "^1.2.0", + "certpem": "^1.1.0", + "le-challenge-fs": "^2.0.2", + "le-sni-auto": "^2.1.3", + "le-store-certbot": "^2.1.7", + "rsa-compat": "^1.5.0" + }, + "description": "Let's Encrypt for node.js on npm", + "devDependencies": { + "request": "^2.75.0" + }, + "directories": {}, + "dist": { + "fileCount": 8, + "integrity": "sha512-vLJ41rhuzmf/DRqceWKXvhoU6yZ8l1b+o3idExea/RANkPT4hs/2qg7hFzjLRngQEYP4LmgeFPbeqPYQV8m+zQ==", + "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb5qlYCRA9TVsSAnZWagAAtEEP/1y3ugTwK2Zt3+QDZoRG\newZwL5KyOAKMGHSWRj/xTHHqh0pm3abE85AqS6DwykRu1H/dam5Y7ncIadNm\nL1vDGP0gMH4l6fWOh6UlyX+zOv2JTNOom3km17ISpydxQugae37iotkOUnSy\n2YauoiGOERDEQfbuHYb16llz8x6Ged2SIfDQdRNOgvL13gCOyKmGZDEYpfD4\nayU/7ZHZaYIe/92cGZ/xzph1oD60bgIyqboMrdvdRGe3hwgpKfib9FHDPPfF\nL/YGPKg8EEc5H5/raK8K4cMt3yX3QCb2rsVMoNMxO6WQyz3nGgv21jFoFz8W\n5vExddJhSo2781eEpXNSdRgwuuTP+AFofvBeAj7KTOQrVvd9Sf9dbYdwWOZ5\nui3xsNFJurX0UdS+VrWm+elExhjsKiF6CWwZQk14KAKAUBTNypHKmwnNQvn1\nreBybwgHCZV1zx4yCe+96p4h4RPDE6PohBJwXMnVPLkITeCldKrzvzQfZyz0\nqfCjuHG6YKc5ZVwqBfTjlOWIaBFN3SoOKhlIhCTvecjPxmCh+GwUkVoTBgpR\nyl641AjqrFNVkDMKTolJIe6TczZ9zpJi+tr/Da8W09QZKBdIVNGVKkENO1kN\nLIQkwm1jRv739lgwRt2OISWcw+/lED+fKxJyAMlPUZquCjRZ/iRz2fDIHmNi\n4h72\r\n=YRwx\r\n-----END PGP SIGNATURE-----\r\n", + "shasum": "59a5878d76fba962aeec0b609b2a7a097a102261", + "tarball": "https://registry.npmjs.org/greenlock/-/greenlock-2.4.10.tgz", + "unpackedSize": 67800 + }, + "engines": { + "node": ">=4.5" + }, + "gitDependencies": { + "acme": "git+https://git.coolaj86.com/coolaj86/acme-.js.git#v1.0", + "le-acme-core": "git+https://git.coolaj86.com/coolaj86/le-acme-core.js.git#v2.1" + }, + "gitHead": "abe081387d13d49a4db55e83e6f0fedc54a1e2e6", + "homepage": "https://git.coolaj86.com/coolaj86/greenlock.js", + "keywords": [ + "ACME", + "Automated HTTPS", + "Free SSL", + "Greenlock", + "Let's Encrypt", + "auto-sni", + "https", + "letsencrypt", + "tls", + "v2" + ], + "license": "(MIT OR Apache-2.0)", + "main": "index.js", + "maintainers": [ + { + "name": "coolaj86", + "email": "coolaj86@gmail.com" + }, + { + "name": "ppl", + "email": "npm@ppl.family" + }, + { + "name": "thejshaver", + "email": "john@jshaver.net" + } + ], + "name": "greenlock", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "https://git.coolaj86.com/coolaj86/greenlock.js.git" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "trulyOptionalDependencies": { + "bluebird": "^3.5.1", + "le-acme-core": "^2.1.3", + "ursa": "^0.9.4" + }, + "version": "2.4.10" +} diff --git a/express-server/node_modules/ipaddr.js/lib/ipaddr.js.d.ts b/express-server/node_modules/ipaddr.js/lib/ipaddr.js.d.ts new file mode 100644 index 00000000..882fa96d --- /dev/null +++ b/express-server/node_modules/ipaddr.js/lib/ipaddr.js.d.ts @@ -0,0 +1,71 @@ + + +declare module "ipaddr.js" { + + type IPv4Range = 'unspecified' | 'broadcast' | 'multicast' | 'linkLocal' | 'loopback' | 'carrierGradeNat' | 'private' | 'reserved'; + type IPv6Range = 'unspecified' | 'linkLocal' | 'multicast' | 'loopback' | 'uniqueLocal' | 'ipv4Mapped' | 'rfc6145' | 'rfc6052' | '6to4' | 'teredo' | 'reserved'; + + interface RangeList { + [name: string]: [T, number] | [T, number][]; + } + + + // Common methods/properties for IPv4 and IPv6 classes. + class IP { + + prefixLengthFromSubnetMask(): number | false; + toByteArray(): number[]; + toNormalizedString(): string; + toString(): string; + } + + namespace Address { + + export function isValid(addr: string): boolean; + export function fromByteArray(bytes: number[]): IPv4 | IPv6; + export function parse(addr: string): IPv4 | IPv6; + export function parseCIDR(mask: string): [IPv4 | IPv6, number]; + export function process(address: string): IPv4 | IPv6; + export function subnetMatch(addr: IPv4, rangeList: RangeList, defaultName?: string): string; + export function subnetMatch(addr: IPv6, rangeList: RangeList, defaultName?: string): string; + + export class IPv4 extends IP { + static broadcastAddressFromCIDR(addr: string): IPv4; + static isIPv4(addr: string): boolean; + static isValidFourPartDecimal(addr: string): boolean; + static isValid(addr: string): boolean; + static networkAddressFromCIDR(addr: string): IPv4; + static parse(addr: string): IPv4; + static parseCIDR(addr: string): [IPv4, number]; + static subnetMaskFromPrefixLength(prefix: number): IPv4; + constructor(octets: number[]); + + kind(): 'ipv4'; + match(addr: IPv4, bits: number): boolean; + match(mask: [IPv4, number]): boolean; + range(): IPv4Range; + subnetMatch(rangeList: RangeList, defaultName?: string): string; + toIPv4MappedAddress(): IPv6; + } + + export class IPv6 extends IP { + static broadcastAddressFromCIDR(addr: string): IPv6; + static isIPv6(addr: string): boolean; + static isValid(addr: string): boolean; + static parse(addr: string): IPv6; + static parseCIDR(addr: string): [IPv6, number]; + static subnetMaskFromPrefixLength(prefix: number): IPv6; + constructor(octets: number[]); + + isIPv4MappedAddress(): boolean; + kind(): 'ipv6'; + match(addr: IPv6, bits: number): boolean; + match(mask: [IPv6, number]): boolean; + range(): IPv6Range; + subnetMatch(rangeList: RangeList, defaultName?: string): string; + toIPv4Address(): IPv4; + } + } + + export = Address; +} diff --git a/express-server/node_modules/le-challenge-fs/.npmignore b/express-server/node_modules/le-challenge-fs/.npmignore new file mode 100644 index 00000000..5148e527 --- /dev/null +++ b/express-server/node_modules/le-challenge-fs/.npmignore @@ -0,0 +1,37 @@ +# Logs +logs +*.log +npm-debug.log* + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules +jspm_packages + +# Optional npm cache directory +.npm + +# Optional REPL history +.node_repl_history diff --git a/express-server/node_modules/le-challenge-fs/LICENSE b/express-server/node_modules/le-challenge-fs/LICENSE new file mode 100644 index 00000000..a7782bc5 --- /dev/null +++ b/express-server/node_modules/le-challenge-fs/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 Daplie, Inc + +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/express-server/node_modules/le-challenge-fs/README.md b/express-server/node_modules/le-challenge-fs/README.md new file mode 100644 index 00000000..04fbc1d0 --- /dev/null +++ b/express-server/node_modules/le-challenge-fs/README.md @@ -0,0 +1,63 @@ +[![Join the chat at https://gitter.im/Daplie/letsencrypt-express](https://badges.gitter.im/Daplie/letsencrypt-express.svg)](https://gitter.im/Daplie/letsencrypt-express?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +| [letsencrypt](https://github.com/Daplie/node-letsencrypt) (library) +| [letsencrypt-cli](https://github.com/Daplie/letsencrypt-cli) +| [letsencrypt-express](https://github.com/Daplie/letsencrypt-express) +| [letsencrypt-cluster](https://github.com/Daplie/letsencrypt-cluster) +| [letsencrypt-koa](https://github.com/Daplie/letsencrypt-koa) +| [letsencrypt-hapi](https://github.com/Daplie/letsencrypt-hapi) +| + +# le-challenge-webroot + +An fs-based strategy for node-letsencrypt for setting, retrieving, +and clearing ACME challenges issued by the ACME server + +This places the acme challenge in an appropriate directory in the specified `webrootPath` +and removes it once the challenge has either completed or failed. + +* Safe to use with node cluster +* Safe to use with ephemeral services (Heroku, Joyent, etc) + +Install +------- + +```bash +npm install --save le-challenge-fs@2.x +``` + +Usage +----- + +```bash +var leChallenge = require('le-challenge-fs').create({ + webrootPath: '~/letsencrypt/srv/www/:hostname/.well-known/acme-challenge' // defaults to os.tmpdir() +, loopbackPort: 5001 // defaults to 80 +, loopbackTimeout: 3000 // defaults to 3000ms +, debug: false +}); + +var LE = require('letsencrypt'); + +LE.create({ + server: LE.stagingServerUrl // Change to LE.productionServerUrl in production +, challenge: leChallenge +}); +``` + +NOTE: If you request a certificate with 6 domains listed, +it will require 6 individual challenges. + +Exposed Methods +--------------- + +For ACME Challenge: + +* `set(opts, domain, key, val, done)` +* `get(defaults, domain, key, done)` +* `remove(defaults, domain, key, done)` + +For node-letsencrypt internals: + +* `getOptions()` returns the internal defaults merged with the user-supplied options +* `loopback(defaults, domain, key, value, done)` test, by external means, that the ACME server's challenge server will succeed diff --git a/express-server/node_modules/le-challenge-fs/index.js b/express-server/node_modules/le-challenge-fs/index.js new file mode 100644 index 00000000..f82cb320 --- /dev/null +++ b/express-server/node_modules/le-challenge-fs/index.js @@ -0,0 +1,121 @@ +'use strict'; + +var fs = require('fs'); +var path = require('path'); + +var myDefaults = { + //webrootPath: [ '~', 'letsencrypt', 'var', 'lib' ].join(path.sep) + webrootPath: path.join(require('os').tmpdir(), 'acme-challenge') +, loopbackTimeout: 5 * 1000 +, debug: false +}; + +var Challenge = module.exports; + +Challenge.create = function (options) { + var results = {}; + + Object.keys(Challenge).forEach(function (key) { + results[key] = Challenge[key]; + }); + results.create = undefined; + + Object.keys(myDefaults).forEach(function (key) { + if ('undefined' === typeof options[key]) { + options[key] = myDefaults[key]; + } + }); + results._options = options; + + results.getOptions = function () { + return results._options; + }; + + return results; +}; + +// +// NOTE: the "args" here in `set()` are NOT accessible to `get()` and `remove()` +// They are provided so that you can store them in an implementation-specific way +// if you need access to them. +// +Challenge.set = function (args, domain, challengePath, keyAuthorization, done) { + var mkdirp = require('mkdirp'); + keyAuthorization = String(keyAuthorization); + + mkdirp(args.webrootPath, function (err) { + if (err) { + done(err); + return; + } + + fs.writeFile(path.join(args.webrootPath, challengePath), keyAuthorization, 'utf8', function (err) { + done(err); + }); + }); +}; + + +// +// NOTE: the "defaults" here are still merged and templated, just like "args" would be, +// but if you specifically need "args" you must retrieve them from some storage mechanism +// based on domain and key +// +Challenge.get = function (defaults, domain, key, done) { + fs.readFile(path.join(defaults.webrootPath, key), 'utf8', done); +}; + +Challenge.remove = function (defaults, domain, key, done) { + fs.unlink(path.join(defaults.webrootPath, key), done); +}; + +Challenge.loopback = function (defaults, domain, key, done) { + var hostname = domain + (defaults.loopbackPort ? ':' + defaults.loopbackPort : ''); + var urlstr = 'http://' + hostname + '/.well-known/acme-challenge/' + key; + + require('http').get(urlstr, function (res) { + if (200 !== res.statusCode) { + done(new Error("local loopback failed with statusCode " + res.statusCode)); + return; + } + var chunks = []; + res.on('data', function (chunk) { + chunks.push(chunk); + }); + res.on('end', function () { + var str = Buffer.concat(chunks).toString('utf8').trim(); + done(null, str); + }); + }).setTimeout(defaults.loopbackTimeout, function () { + done(new Error("loopback timeout, could not reach server")); + }).on('error', function (err) { + done(err); + }); +}; + +Challenge.test = function (args, domain, challenge, keyAuthorization, done) { + var me = this; + var key = keyAuthorization || challenge; + + me.set(args, domain, challenge, key, function (err) { + if (err) { done(err); return; } + + myDefaults.loopbackPort = args.loopbackPort; + myDefaults.webrootPath = args.webrootPath; + me.loopback(args, domain, challenge, function (err, _key) { + if (err) { done(err); return; } + + if (key !== _key) { + err = new Error("keyAuthorization [original] '" + key + "'" + + " did not match [result] '" + _key + "'"); + return; + } + + me.remove(myDefaults, domain, challenge, function (_err) { + if (_err) { done(_err); return; } + + done(err); + }); + }); + }); +}; diff --git a/express-server/node_modules/le-challenge-fs/package.json b/express-server/node_modules/le-challenge-fs/package.json new file mode 100644 index 00000000..6d18ea47 --- /dev/null +++ b/express-server/node_modules/le-challenge-fs/package.json @@ -0,0 +1,100 @@ +{ + "_args": [ + [ + "le-challenge-fs@^2.0.8", + "/nodeapps/https-test/greenlock-express.js" + ] + ], + "_from": "le-challenge-fs@>=2.0.8 <3.0.0", + "_id": "le-challenge-fs@2.0.8", + "_inCache": true, + "_installable": true, + "_location": "/le-challenge-fs", + "_nodeVersion": "6.7.0", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/le-challenge-fs-2.0.8.tgz_1476312857466_0.7560109794139862" + }, + "_npmUser": { + "email": "coolaj86@gmail.com", + "name": "coolaj86" + }, + "_npmVersion": "3.10.3", + "_phantomChildren": {}, + "_requested": { + "name": "le-challenge-fs", + "raw": "le-challenge-fs@^2.0.8", + "rawSpec": "^2.0.8", + "scope": null, + "spec": ">=2.0.8 <3.0.0", + "type": "range" + }, + "_requiredBy": [ + "/", + "/greenlock" + ], + "_resolved": "https://registry.npmjs.org/le-challenge-fs/-/le-challenge-fs-2.0.8.tgz", + "_shasum": "b6d458a37f097e87df3d8b5ff67013737ab9d5a2", + "_shrinkwrap": null, + "_spec": "le-challenge-fs@^2.0.8", + "_where": "/nodeapps/https-test/greenlock-express.js", + "author": { + "email": "coolaj86@gmail.com", + "name": "AJ ONeal", + "url": "https://coolaj86.com/" + }, + "bugs": { + "url": "https://github.com/Daplie/le-challenge-fs/issues" + }, + "dependencies": { + "mkdirp": "^0.5.1" + }, + "description": "A fs-based strategy for node-letsencrypt for setting, retrieving, and clearing ACME challenges issued by the ACME server", + "devDependencies": { + "finalhandler": "^0.5.0", + "serve-static": "^1.11.1" + }, + "directories": {}, + "dist": { + "shasum": "b6d458a37f097e87df3d8b5ff67013737ab9d5a2", + "tarball": "https://registry.npmjs.org/le-challenge-fs/-/le-challenge-fs-2.0.8.tgz" + }, + "gitHead": "3cc123034837d6e3535937665f2227b80d9cb535", + "homepage": "https://github.com/Daplie/le-challenge-fs#readme", + "keywords": [ + "acme", + "challenge", + "cluster", + "ephemeral", + "fs", + "http", + "http-01", + "le", + "le-challenge", + "le-challenge-", + "le-challenge-fs", + "le-challenge-http", + "le-challenge-webroot", + "letsencrypt", + "webroot" + ], + "license": "(MIT OR Apache-2.0)", + "main": "index.js", + "maintainers": [ + { + "name": "coolaj86", + "email": "coolaj86@gmail.com" + } + ], + "name": "le-challenge-fs", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/Daplie/le-challenge-fs.git" + }, + "scripts": { + "test": "node test.js" + }, + "version": "2.0.8" +} diff --git a/express-server/node_modules/le-challenge-fs/test.js b/express-server/node_modules/le-challenge-fs/test.js new file mode 100644 index 00000000..79a768c8 --- /dev/null +++ b/express-server/node_modules/le-challenge-fs/test.js @@ -0,0 +1,72 @@ +'use strict'; + +//var httpsOptions = require('localhost.daplie.com-certificates').merge({}); +var webrootPath = '/tmp/acme-challenge'; +var challenge = require('./').create({ debug: true, webrootPath: webrootPath }); + +var opts = challenge.getOptions(); +var domain = 'example.com'; +var token = 'token-id'; +var key = 'secret-key'; + +challenge.remove(opts, domain, token, function () { + // ignore error, if any + + challenge.set(opts, domain, token, key, function (err) { + // if there's an error, there's a problem + if (err) { throw err; } + + // throw new Error("manually check /tmp/acme-challenge"); + + challenge.get(opts, domain, token, function (err, _key) { + // if there's an error, there's a problem + if (err) { throw err; } + + // should retrieve the key + if (key !== _key) { + throw new Error("FAIL: could not get key by token"); + } + + challenge.remove(opts, domain, token, function () { + // if there's an error, there's a problem + if (err) { throw err; } + + challenge.get(opts, domain, token, function (err, _key) { + // error here is okay + + // should NOT retrieve the key + if (_key) { + throw new Error("FAIL: should not get key"); + } + + console.info('[PASS] unit test'); + }); + }); + }); + }); +}); + +function loopbackTest() { + var http = require('http'); + var serveStatic = require('serve-static')(webrootPath, { dotfiles: 'allow' }); + var finalhandler = require('finalhandler'); + var server = http.createServer(function (req, res) { + req.url = req.url.replace(/^\/\.well-known\/acme-challenge\//, '/'); + serveStatic(req, res, finalhandler(req, res)); + }); + + server.listen(0, function () { + var port = server.address().port; + + opts.webrootPath = webrootPath; + opts.loopbackPort = port; + opts.loopbackTimeout = 500; + challenge.test(opts, 'localhost', 'foo', 'bar', function (err) { + server.close(); + if (err) { console.error(err.stack); return; } + + console.info('[PASS] localhost loopback'); + }); + }); +} +loopbackTest(); diff --git a/express-server/node_modules/le-sni-auto/LICENSE b/express-server/node_modules/le-sni-auto/LICENSE new file mode 100644 index 00000000..a7782bc5 --- /dev/null +++ b/express-server/node_modules/le-sni-auto/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 Daplie, Inc + +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/express-server/node_modules/le-sni-auto/README.md b/express-server/node_modules/le-sni-auto/README.md new file mode 100644 index 00000000..8628f23e --- /dev/null +++ b/express-server/node_modules/le-sni-auto/README.md @@ -0,0 +1,194 @@ +le-sni-auto +=========== + +| Sponsored by [ppl](https://ppl.family) + +An auto-sni strategy for registering and renewing letsencrypt certificates using SNICallback. + +This does a couple of rather simple things: + + * caches certificates in memory + * calls `getCertificatesAsync(domain, null)` when a certificate is not in memory + * calls `getCertificatesASync(domain, certs)` when a certificate is up for renewal or expired + +Install +======= + +```bash +npm install --save le-sni-auto@2.x +``` + +Usage +===== + +With node-letsencrypt +--------------------- + +```javascript +'use strict'; + + + +var leSni = require('le-sni-auto').create({ + + renewWithin: 14 * 24 * 60 * 60 1000 // do not renew more than 14 days before expiration +, renewBy: 10 * 24 * 60 * 60 1000 // do not wait more than 10 days before expiration + +, tlsOptions: { + rejectUnauthorized: true // These options will be used with tls.createSecureContext() + , requestCert: false // in addition to key (privkey.pem) and cert (cert.pem + chain.pem), + , ca: null // which are provided by letsencrypt + , crl: null + } + +}); + + + +var le = require('letsencrypt').create({ + server: 'staging' + +, sni: leSni + +, approveDomains: function (domain, cb) { + // here you would lookup details such as email address in your db + cb(null, { email: 'john.doe@gmail.com.', domains: [domain, 'www.' + domain], agreeTos: true }} + } +}); + + + +var redirectHttps = require('redirect-https').create(); +http.createServer(le.middleware(redirectHttps)); + + + +var app = require('express')(); +https.createServer(le.tlsOptions, le.middleware(app)).listen(443); +``` + +You can also provide a thunk-style `getCertificates(domain, certs, cb)`. + +Standalone +---------- + +```javascript +'use strict'; + + + +var leSni = require('le-sni-auto').create({ + renewWithin: 14 * 24 * 60 * 60 1000 // do not renew prior to 10 days before expiration +, renewBy: 10 * 24 * 60 * 60 1000 // do not wait more than 5 days before expiration + + // key (privkey.pem) and cert (cert.pem + chain.pem) will be provided by letsencrypt +, tlsOptions: { rejectUnauthorized: true, requestCert: false, ca: null, crl: null } + +, getCertificatesAsync: function (domain, certs) { + // return a promise with an object with the following keys: + // { privkey, cert, chain, expiresAt, issuedAt, subject, altnames } + } +}); + + + +var tlsOptions = { + SNICallback: leSni.sniCallback +}; + +https.createServer(tlsOptions, app); +``` + +You can also provide a thunk-style `getCertificates(domain, certs, cb)`. + +API +=== + +* create(options) + * `getCertificates(domain, certs, cb)` or `getCertificatesAsync(domain, certs)` + * `renewWithin` (default 7 days, min 3 days) + * `renewBy` (default 2 days, min 12 hours) +* `sniCallback(domain, cb)` +* `cacheCerts(certs)` +* `uncacheDomain(domain)` + +.renewWithin +----------- + +Specifies the maximum amount of time (in ms) before +the certificate expires to renew it. + +Say the cert expires in 90 days and you would like +to renew, **at earliest** 10 days before it expires. + +You would set this to `10 * 24 * 60 * 60 * 1000`. + +.renewBy +-------- + +Specifies the maximum amount of time (in ms) before +the certificate expires to renew it. + +Say the cert expires in 90 days and you would like +to renew, **at latest** 10 days before it expires. + +You would set this to `10 * 24 * 60 * 60 * 1000`. + +**MUST** be **less than** `renewWithin`. + +.sniCallback() +----------- + +This gets passed to `https.createServer(tlsOptions, app)` as `tlsOptions.SNICallback`. + +```javascript +var leSni = require('le-sni-auto').create({ + renewWithin: 14 * 24 * 60 * 60 1000 +}); + +var tlsOptions = { + SNICallback: leSni.sniCallback +}; + +function app(req, res) { + res.end("Hello, World!"); +} + +https.createServer(tlsOptions, app); +``` + +.cacheCerts() +----------- + +Manually load a certificate into the cache. + +This is useful in a cluster environment where the master +may wish to inform multiple workers of a new or renewed certificate, +or to satisfy tls-sni-01 challenges. + +``` +leSni.cacheCerts({ +, privkey: '<>' +, cert: '<>' +, subject: 'example.com' +, altnames: [ 'example.com', 'www.example.com' ] +, issuedAt: 1470975565000 +, expiresAt: 1478751565000 +, auto: true +}); +``` + +.uncacheCerts() +----------- + +Remove cached certificates from the cache. + +This is useful once a tls-sni-01 challenge has been satisfied. + +``` +leSni.uncacheCerts({ +, subject: 'example.com' +, altnames: [ 'example.com', 'www.example.com' ] +}); +``` + diff --git a/express-server/node_modules/le-sni-auto/index.js b/express-server/node_modules/le-sni-auto/index.js new file mode 100644 index 00000000..3fc0c1a9 --- /dev/null +++ b/express-server/node_modules/le-sni-auto/index.js @@ -0,0 +1,172 @@ +'use strict'; + +var DAY = 24 * 60 * 60 * 1000; +var HOUR = 60 * 60 * 1000; +var MIN = 60 * 1000; +var defaults = { + // don't renew before the renewWithin period + renewWithin: 30 * DAY +, _renewWithinMin: 3 * DAY + // renew before the renewBy period +, renewBy: 21 * DAY +, _renewByMin: Math.floor(DAY / 2) + // just to account for clock skew really +, _dropDead: 5 * MIN +}; + +// autoSni = { renewWithin, renewBy, getCertificates, tlsOptions, _dbg_now } +module.exports.create = function (autoSni) { + + if (!autoSni.getCertificatesAsync) { autoSni.getCertificatesAsync = require('bluebird').promisify(autoSni.getCertificates); } + if (!autoSni.renewWithin) { autoSni.renewWithin = autoSni.notBefore || defaults.renewWithin; } + if (autoSni.renewWithin < defaults._renewWithinMin) { + throw new Error("options.renewWithin should be at least " + (defaults._renewWithinMin / DAY) + " days"); + } + if (!autoSni.renewBy) { autoSni.renewBy = autoSni.notAfter || defaults.renewBy; } + if (autoSni.renewBy < defaults._renewByMin) { + throw new Error("options.renewBy should be at least " + (defaults._renewBy / HOUR) + " hours"); + } + if (!autoSni.tlsOptions) { autoSni.tlsOptions = autoSni.httpsOptions || {}; } + + + + + autoSni._dropDead = defaults._dropDead; + //autoSni.renewWithin = autoSni.notBefore; // i.e. 15 days + autoSni._renewWindow = autoSni.renewWithin - autoSni.renewBy; // i.e. 1 day + //autoSni.renewRatio = autoSni.notBefore = autoSni._renewWindow; // i.e. 1/15 (6.67%) + + + + + var tls = require('tls'); + + + + + var _autoSni = { + + + + + // in-process cache + _ipc: {} + , getOptions: function () { + return JSON.parse(JSON.stringify(defaults)); + } + + + + + // cache and format incoming certs + , cacheCerts: function (certs) { + var meta = { + certs: certs + , tlsContext: 'string' === typeof certs.cert && tls.createSecureContext({ + key: certs.privkey + // backwards/forwards compat + , cert: (certs.cert||'').replace(/[\r\n]+$/, '') + '\r\n' + certs.chain + , rejectUnauthorized: autoSni.tlsOptions.rejectUnauthorized + + , requestCert: autoSni.tlsOptions.requestCert // request peer verification + , ca: autoSni.tlsOptions.ca // this chain is for incoming peer connctions + , crl: autoSni.tlsOptions.crl // this crl is for incoming peer connections + }) || { '_fake_tls_context_': true } + + , subject: certs.subject + , auto: 'undefined' === typeof certs.auto ? true : certs.auto + // stagger renewal time by a little bit of randomness + , renewAt: (certs.expiresAt - (autoSni.renewWithin - (autoSni._renewWindow * Math.random()))) + // err just barely on the side of safety + , expiresNear: certs.expiresAt - autoSni._dropDead + }; + var link = { subject: certs.subject }; + + certs.altnames.forEach(function (domain) { + autoSni._ipc[domain] = link; + }); + autoSni._ipc[certs.subject] = meta; + + return meta; + } + + + + + , uncacheCerts: function (certs) { + certs.altnames.forEach(function (domain) { + delete autoSni._ipc[domain]; + }); + delete autoSni._ipc[certs.subject]; + } + + + + + // automate certificate registration on request + , sniCallback: function (domain, cb) { + var certMeta = autoSni._ipc[domain]; + var promise; + var now = (autoSni._dbg_now || Date.now()); + + if (certMeta && !certMeta.then && certMeta.subject !== domain) { + //log(autoSni.debug, "LINK CERT", domain); + certMeta = autoSni._ipc[certMeta.subject]; + } + + if (!certMeta) { + //log(autoSni.debug, "NO CERT", domain); + // we don't have a cert and must get one + promise = autoSni.getCertificatesAsync(domain, null).then(autoSni.cacheCerts); + autoSni._ipc[domain] = promise; + } + else if (certMeta.then) { + //log(autoSni.debug, "PROMISED CERT", domain); + // we are already getting a cert + promise = certMeta + } + else if (now >= certMeta.expiresNear) { + //log(autoSni.debug, "EXPIRED CERT"); + // we have a cert, but it's no good for the average user + promise = autoSni.getCertificatesAsync(domain, certMeta.certs).then(autoSni.cacheCerts); + autoSni._ipc[certMeta.subject] = promise; + } else { + + // it's time to renew the cert + if (certMeta.auto && now >= certMeta.renewAt) { + //log(autoSni.debug, "RENEWABLE CERT"); + // give the cert some time (2-5 min) to be validated and replaced before trying again + certMeta.renewAt = (autoSni._dbg_now || Date.now()) + (2 * MIN) + (3 * MIN * Math.random()); + // let the update happen in the background + autoSni.getCertificatesAsync(domain, certMeta.certs).then(autoSni.cacheCerts); + } + + // return the valid cert right away + cb(null, certMeta.tlsContext); + return; + } + + // promise the non-existent or expired cert + promise.then(function (certMeta) { + cb(null, certMeta.tlsContext); + }, function (err) { + // console.error('ERROR in le-sni-auto:'); + // console.error(err.stack || err); + cb(err); + // don't reuse this promise + delete autoSni._ipc[certMeta && certMeta.subject ? certMeta.subject : domain]; + }); + } + + + + + }; + + Object.keys(_autoSni).forEach(function (key) { + autoSni[key] = _autoSni[key]; + }); + _autoSni = null; + + return autoSni; +}; diff --git a/express-server/node_modules/le-sni-auto/package.json b/express-server/node_modules/le-sni-auto/package.json new file mode 100644 index 00000000..f4bcef8f --- /dev/null +++ b/express-server/node_modules/le-sni-auto/package.json @@ -0,0 +1,98 @@ +{ + "_args": [ + [ + "le-sni-auto@^2.1.4", + "/nodeapps/https-test/greenlock-express.js" + ] + ], + "_from": "le-sni-auto@>=2.1.4 <3.0.0", + "_hasShrinkwrap": false, + "_id": "le-sni-auto@2.1.6", + "_inCache": true, + "_installable": true, + "_location": "/le-sni-auto", + "_nodeVersion": "10.13.0", + "_npmOperationalInternal": { + "host": "s3://npm-registry-packages", + "tmp": "tmp/le-sni-auto_2.1.6_1541843237023_0.4202196992257634" + }, + "_npmUser": { + "email": "coolaj86@gmail.com", + "name": "coolaj86" + }, + "_npmVersion": "6.4.1", + "_phantomChildren": {}, + "_requested": { + "name": "le-sni-auto", + "raw": "le-sni-auto@^2.1.4", + "rawSpec": "^2.1.4", + "scope": null, + "spec": ">=2.1.4 <3.0.0", + "type": "range" + }, + "_requiredBy": [ + "/", + "/greenlock" + ], + "_resolved": "https://registry.npmjs.org/le-sni-auto/-/le-sni-auto-2.1.6.tgz", + "_shasum": "32a00bfb2364814d57670b0c2e28e5e32bb08b00", + "_shrinkwrap": null, + "_spec": "le-sni-auto@^2.1.4", + "_where": "/nodeapps/https-test/greenlock-express.js", + "author": { + "email": "coolaj86@gmail.com", + "name": "AJ ONeal", + "url": "https://coolaj86.com/" + }, + "bugs": { + "url": "https://git.coolaj86.com/coolaj86/le-sni-auto.js/issues" + }, + "dependencies": { + "bluebird": "^3.5.1" + }, + "description": "An auto-sni strategy for registering and renewing letsencrypt certificates using SNICallback", + "devDependencies": {}, + "directories": {}, + "dist": { + "fileCount": 5, + "integrity": "sha512-LcfkF2yQ1nrep+ZfyG+SfR3pHphKFD3zMZ9FKervGfTfvgScCv/XGbX+vxsGZEKZjvzxKbFZ/5LdSCXuLXUU6A==", + "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb5qklCRA9TVsSAnZWagAAMQgQAJBe7o5sWViVB3xBrs+V\ngUVOFRVv1PyoeL4oYeJ0vM3nkw29OBLqf4ZuP5hyl7HquWVd1JGWLEdJGnkL\nF4+PVcgbFQtVC9/yecCeVXHZ5b4K14GSHIpKp3awxV0yGZQtU4tPQcF15BQV\nYGqLF8epvi5229V24CMqfMyMh8rRPdTEIA3zNG9utz7/sgRAgBCONApm1J/x\nXCpIH15B133U4ig0426KXYco98ddlrLfZKdnVBrSSoORhVpTUiigWRduibYP\neGXKC78ORyXZ1kS8K19USM2KFBZj9IuNQ+xEjkw4nkRex4p33rJtaLxtMzso\ncr9qxLzJUAWrdOCbGVPrhMCCyo9068iHMYehEtDsyYL/KxBdoeWKvpfDl8lY\nGWU5IazTkRFT2cQF9CzvFgY1tsPDzrvVGFZEnJoZ7d4TLwjpB6jyucF1T+hL\no+EN1Qr3IZFaAoYyxWEsNbZOpftWsg9/M9rE30w4hhoPuU1N8L84EQGFEZo9\nxwJOZkH4/xULhipVCP3LVNlln+PSumxtasV9+f9mzYshtHhHoNcvwFtrL3VB\nafdccue0AsF+shdgpPPV2G/b9o0goKlP3uT4GrpmKLIMGHy8j+JOsvLkgS+i\nwR9J3HgjGTGFunXqneXsV+BGUbltCmX9IwhWLXwMoJhiSszhH8VWygkOHTwG\nTDna\r\n=ItG1\r\n-----END PGP SIGNATURE-----\r\n", + "shasum": "32a00bfb2364814d57670b0c2e28e5e32bb08b00", + "tarball": "https://registry.npmjs.org/le-sni-auto/-/le-sni-auto-2.1.6.tgz", + "unpackedSize": 17428 + }, + "gitHead": "14458181bf07ad8429e961e92561396e23f41196", + "homepage": "https://git.coolaj86.com/coolaj86/le-sni-auto.js", + "keywords": [ + "SNICallback", + "auto-sni", + "certbot", + "le-sni", + "le-sni-", + "letsencrypt", + "sni-auto" + ], + "license": "(MIT OR Apache-2.0)", + "main": "index.js", + "maintainers": [ + { + "name": "coolaj86", + "email": "coolaj86@gmail.com" + }, + { + "name": "ppl", + "email": "npm@ppl.family" + } + ], + "name": "le-sni-auto", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://git.coolaj86.com/coolaj86/le-sni-auto.js.git" + }, + "scripts": { + "test": "node test.js" + }, + "version": "2.1.6" +} diff --git a/express-server/node_modules/le-sni-auto/test.js b/express-server/node_modules/le-sni-auto/test.js new file mode 100644 index 00000000..3f52d57e --- /dev/null +++ b/express-server/node_modules/le-sni-auto/test.js @@ -0,0 +1,205 @@ +'use strict'; + +var DAY = 24 * 60 * 60 * 1000; +var MIN = 60 * 1000; +var START_DAY = new Date(2015, 0, 1, 17, 30, 0, 0).valueOf(); +var NOT_BEFORE = 10 * DAY; +var NOT_AFTER = 5 * DAY; +var EXPIRES_AT = START_DAY + NOT_BEFORE + (15 * MIN); +var RENEWABLE_DAY = EXPIRES_AT - (60 * MIN); +var CERT_1 = { + expiresAt: EXPIRES_AT +, subject: 'example.com' +, altnames: ['example.com', 'www.example.com'] +}; +var CERT_2 = { + expiresAt: EXPIRES_AT + NOT_BEFORE + (60 * MIN) +, subject: 'example.com' +, altnames: ['example.com', 'www.example.com'] +}; +var CERT_3 = { + expiresAt: EXPIRES_AT +, subject: 'example.com' +, altnames: ['example.com', 'www.example.com'] +, auto: false +}; + +var count = 0; +var expectedCount = 4; +var tests = [ + function (domain, certs, cb) { + count += 1; + console.log('#1 is 1 of 4'); + if (!domain) { + throw new Error("should have a domain"); + } + + if (certs) { + console.log('certs'); + console.log(certs); + throw new Error("shouldn't have certs that don't even exist yet"); + } + + cb(null, CERT_1); + } +, function (/*domain, certs, cb*/) { + console.log('#2 should NOT be called'); + throw new Error("Should not call register renew a certificate with more than 10 days left"); + } +, function (domain, certs, cb) { + count += 1; + console.log('#3 is 2 of 4'); + // NOTE: there's a very very small chance this will fail occasionally (if Math.random() < 0.01) + if (!certs) { + throw new Error("should have certs to renew (renewAt)"); + } + + cb(null, CERT_1); + } +, function (domain, certs, cb) { + count += 1; + console.log('#4 is 3 of 4'); + if (!certs) { + throw new Error("should have certs to renew (expiresNear)"); + } + + cb(null, CERT_2); + } +, function (/*domain, certs, cb*/) { + console.log('#5 should NOT be called'); + throw new Error("Should not call register renew a certificate with more than 10 days left"); + } +, function (domain, certs, cb) { + count += 1; + console.log('#6 is 4 of 4'); + if (certs) { + throw new Error("should not have certs that have been uncached"); + } + + cb(null, CERT_3); + } +, function (/*domain, certs, cb*/) { + console.log('#7 should NOT be called'); + throw new Error("Should not call register renew a non-auto certificate"); + } +].map(function (fn) { + return require('bluebird').promisify(fn); +}); + +// opts = { notBefore, notAfter, letsencrypt.renew, letsencrypt.register, tlsOptions } +var leSni = require('./').create({ + notBefore: NOT_BEFORE +, notAfter: NOT_AFTER +, getCertificatesAsync: tests.shift() +, _dbg_now: START_DAY +}); + +var shared = 0; +var expectedShared = 3; +leSni.sniCallback('example.com', function (err, tlsContext) { + if (err) { throw err; } + shared += 1; +}); +leSni.sniCallback('example.com', function (err, tlsContext) { + if (err) { throw err; } + if (!tlsContext._fake_tls_context_) { + throw new Error("Did not return tlsContext #1"); + } + leSni.getCertificatesAsync = tests.shift(); + + + + + leSni.sniCallback('example.com', function (err, tlsContext) { + if (err) { throw err; } + if (!tlsContext._fake_tls_context_) { + throw new Error("Did not return tlsContext #2"); + } + leSni.getCertificatesAsync = tests.shift(); + + leSni._dbg_now = RENEWABLE_DAY; + + + + + leSni.sniCallback('www.example.com', function (err, tlsContext) { + if (err) { throw err; } + shared += 1; + }); + leSni.sniCallback('example.com', function (err, tlsContext) { + if (err) { throw err; } + if (!tlsContext._fake_tls_context_) { + throw new Error("Did not return tlsContext #3"); + } + leSni.getCertificatesAsync = tests.shift(); + + leSni._dbg_now = EXPIRES_AT; + + + + + leSni.sniCallback('www.example.com', function (err, tlsContext) { + if (err) { throw err; } + shared += 1; + }); + leSni.sniCallback('www.example.com', function (err, tlsContext) { + if (err) { throw err; } + if (!tlsContext._fake_tls_context_) { + throw new Error("Did not return tlsContext #4"); + } + leSni.getCertificatesAsync = tests.shift(); + + + + + leSni.sniCallback('www.example.com', function (err, tlsContext) { + if (err) { throw err; } + if (!tlsContext._fake_tls_context_) { + throw new Error("Did not return tlsContext #5"); + } + leSni.uncacheCerts({ + subject: 'example.com' + , altnames: ['example.com', 'www.example.com'] + }); + leSni.getCertificatesAsync = tests.shift(); + + + + + leSni.sniCallback('example.com', function (err, tlsContext) { + if (err) { throw err; } + if (!tlsContext._fake_tls_context_) { + throw new Error("Did not return tlsContext #6"); + } + leSni.getCertificatesAsync = tests.shift(); + + leSni._dbg_now = RENEWABLE_DAY; + + + + + leSni.sniCallback('example.com', function (err, tlsContext) { + if (!tlsContext._fake_tls_context_) { + throw new Error("Did not return tlsContext #7"); + } + + if (expectedCount !== count) { + throw new Error("getCertificate only called " + count + " times"); + } + + if (expectedShared !== shared) { + throw new Error("wrongly used only " + shared + " shared promises"); + } + + if (tests.length) { + throw new Error("some test functions not run"); + } + + console.log('PASS'); + }); + }); + }); + }); + }); + }); +}); diff --git a/express-server/node_modules/le-store-certbot/LICENSE b/express-server/node_modules/le-store-certbot/LICENSE new file mode 100644 index 00000000..a7782bc5 --- /dev/null +++ b/express-server/node_modules/le-store-certbot/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 Daplie, Inc + +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/express-server/node_modules/le-store-certbot/README.md b/express-server/node_modules/le-store-certbot/README.md new file mode 100644 index 00000000..b1798983 --- /dev/null +++ b/express-server/node_modules/le-store-certbot/README.md @@ -0,0 +1,75 @@ +le-store-certbot +================ + +The "certbot" storage strategy for +[Greenlock.js](https://git.coolaj86.com/coolaj86/le-store-certbot.js). + +This le storage strategy aims to maintain compatibility with the +configuration files and file structure of the official certbot client. + +Note: You cannot use this strategy on ephemeral instances (heroku, aws elastic). + +Usage +----- + +```bash +npm install --save le-store-certbot@2.x +``` + +```bash +var leStore = require('le-store-certbot').create({ + configDir: require('homedir')() + '/acme/etc' // or /etc/acme or wherever +, privkeyPath: ':configDir/live/:hostname/privkey.pem' // +, fullchainPath: ':configDir/live/:hostname/fullchain.pem' // Note: both that :configDir and :hostname +, certPath: ':configDir/live/:hostname/cert.pem' // will be templated as expected by +, chainPath: ':configDir/live/:hostname/chain.pem' // greenlock.js + +, logsDir: require('homedir')() + '/tmp/acme/log' + +, webrootPath: '~/acme/srv/www/:hostname/.well-known/acme-challenge' + +, debug: false +}); +``` + +The store module can be used globally with Greenlock like this: + +``` +var Greenlock = require('greenlock'); + +Greenlock.create({ + ... +, store: leStore +}); +``` + +Example File Structure +---------------------- + +``` +~/acme/ +└── etc + ├── accounts + │   └── acme-staging.api.letsencrypt.org + │   └── directory + │   └── cd96ac4889ddfa47bfc66300ab223342 + │   ├── meta.json + │   ├── private_key.json + │   └── regr.json + ├── archive + │   └── example.com + │   ├── cert0.pem + │   ├── chain0.pem + │   ├── fullchain0.pem + │   └── privkey0.pem + ├── live + │   └── example.com + │   ├── cert.pem + │   ├── chain.pem + │   ├── fullchain.pem + │   ├── privkey.pem + │   └── privkey.pem.bak + └── renewal + ├── example.com.conf + └── example.com.conf.bak +``` diff --git a/express-server/node_modules/le-store-certbot/index.js b/express-server/node_modules/le-store-certbot/index.js new file mode 100644 index 00000000..90011f32 --- /dev/null +++ b/express-server/node_modules/le-store-certbot/index.js @@ -0,0 +1,661 @@ +'use strict'; +/* global Promise */ + +var PromiseA; +try { + PromiseA = require('bluebird'); +} catch(e) { + PromiseA = Promise; +} +var util = require('util'); +function promisifyAll(obj) { + var aobj = {}; + Object.keys(obj).forEach(function (key) { + aobj[key + 'Async'] = util.promisify(obj[key]); + }); + return aobj; +} +var mkdirpAsync = util.promisify(require('mkdirp')); +var path = require('path'); +var fs = require('fs'); +var readFileAsync = util.promisify(fs.readFile); +var readdirAsync = util.promisify(fs.readdir); +var writeFileAsync = util.promisify(fs.writeFile); +var statAsync = util.promisify(fs.stat); +var sfs = require('safe-replace'); +var os = require('os'); + +function log(debug) { + if (debug) { + var args = Array.prototype.slice.call(arguments); + args.shift(); + args.unshift("[le-store-certbot]"); + console.log.apply(console, args); + } +} + +function writeRenewalConfig(args) { + var pyobj = args.pyobj; + pyobj.checkpoints = parseInt(pyobj.checkpoints, 10) || 0; + + var pyconf = promisifyAll(require('pyconf')); + + var liveDir = args.liveDir || path.join(args.configDir, 'live', args.domains[0]); + + var certPath = args.certPath || pyobj.cert || path.join(liveDir, 'cert.pem'); + var fullchainPath = args.fullchainPath || pyobj.fullchain || path.join(liveDir, 'fullchain.pem'); + var chainPath = args.chainPath || pyobj.chain || path.join(liveDir, 'chain.pem'); + var privkeyPath = args.privkeyPath || pyobj.privkey + //|| args.domainPrivateKeyPath || args.domainKeyPath || pyobj.keyPath + || path.join(liveDir, 'privkey.pem'); + + log(args.debug, 'writeRenewalConfig privkeyPath', privkeyPath); + + var updates = { + account: args.account.id + , configDir: args.configDir + , domains: args.domains + + , email: args.email + , tos: args.agreeTos && true + // yes, it's an array. weird, right? + , webrootPath: args.webrootPath && [args.webrootPath] || [] + , server: args.server || args.acmeDiscoveryUrl + + , privkey: privkeyPath + , fullchain: fullchainPath + , cert: certPath + , chain: chainPath + + , http01Port: args.http01Port + , keyPath: args.domainPrivateKeyPath || args.privkeyPath + , rsaKeySize: args.rsaKeySize + , checkpoints: pyobj.checkpoints + /* // TODO XXX what's the deal with these? they don't make sense + // are they just old junk? or do they have a meaning that I don't know about? + , fullchainPath: path.join(args.configDir, 'chain.pem') + , certPath: path.join(args.configDir, 'cert.pem') + , chainPath: path.join(args.configDir, 'chain.pem') + */ // TODO XXX end + , workDir: args.workDir + , logsDir: args.logsDir + }; + + // final section is completely dynamic + // :hostname = :webroot_path + args.domains.forEach(function (hostname) { + updates[hostname] = args.webrootPath; + }); + + // must write back to the original pyobject or + // annotations will be lost + Object.keys(updates).forEach(function (key) { + pyobj[key] = updates[key]; + }); + + return mkdirpAsync(path.dirname(args.renewalPath)).then(function () { + return pyconf.writeFileAsync(args.renewalPath, pyobj); + }).then(function () { + // NOTE + // writing twice seems to causes a bug, + // so instead we re-read the file from the disk + return pyconf.readFileAsync(args.renewalPath); + }); +} + +function pyToJson(pyobj) { + if (!pyobj) { + return null; + } + + var jsobj = {}; + Object.keys(pyobj).forEach(function (key) { + jsobj[key] = pyobj[key]; + }); + jsobj.__lines = undefined; + jsobj.__keys = undefined; + + return jsobj; +} + +var crypto = require('crypto'); +var rnd = crypto.randomBytes(8).toString('hex'); +var defaults = { + configDir: [ os.homedir(), 'letsencrypt', 'etc' ].join(path.sep) // /etc/letsencrypt/ +, logsDir: [ os.tmpdir(), 'acme-' + rnd, 'log' ].join(path.sep) // /var/log/letsencrypt/ +, webrootPath: [ os.tmpdir(), 'acme-' + rnd, 'acme-challenge' ].join(path.sep) + +, accountsDir: [ ':configDir', 'accounts', ':serverDir' ].join(path.sep) +, renewalPath: [ ':configDir', 'renewal', ':hostname.conf' ].join(path.sep) +, renewalDir: [ ':configDir', 'renewal', '' ].join(path.sep) +, serverDirGet: function (copy) { + return (copy.server || '').replace('https://', '').replace(/(\/)$/, '').replace(/\//g, path.sep); + } + +, privkeyPath: ':configDir/live/:hostname/privkey.pem'.split(/\//).join(path.sep) +, fullchainPath: [ ':configDir', 'live', ':hostname', 'fullchain.pem' ].join(path.sep) +, certPath: [ ':configDir', 'live', ':hostname', 'cert.pem' ].join(path.sep) +, chainPath: [ ':configDir', 'live', ':hostname', 'chain.pem' ].join(path.sep) +, bundlePath: [ ':configDir', 'live', ':hostname', 'bundle.pem' ].join(path.sep) + +, rsaKeySize: 2048 +}; + +module.exports.create = function (configs) { + var mergedConfigs; + + var store = { + getOptions: function () { + if (mergedConfigs) { + return configs; + } + + if (!configs.domainKeyPath) { + configs.domainKeyPath = configs.privkeyPath || defaults.privkeyPath; + } + + Object.keys(defaults).forEach(function (key) { + if (!configs[key]) { + configs[key] = defaults[key]; + } + }); + + mergedConfigs = configs; + return configs; + } + + , keypairs: { + checkAsync: function (keypath, format) { + if (!keypath) { + return null; + } + return readFileAsync(keypath, 'ascii').then(function (key) { + if ('jwk' === format) { + return { privateKeyJwk: JSON.parse(key) }; + } + else { + return { privateKeyPem: key }; + } + }, function (err) { + if ('ENOENT' !== err.code) { + throw err; + } + + return null; + }); + } + , setAsync: function (keypath, keypair, format) { + return mkdirpAsync(path.dirname(keypath)).then(function () { + var key; + + if ('jwk' === format) { + key = JSON.stringify(keypair.privateKeyJwk, null, ' '); + } + else { + key = keypair.privateKeyPem; + } + + return writeFileAsync(keypath, key, 'ascii').then(function () { + return keypair; + }); + }); + } + } + + // + // Certificates + // + , certificates: { + // Certificates + checkKeypairAsync: function (args) { + if (!args.domainKeyPath) { + return PromiseA.reject(new Error("missing options.domainKeyPath")); + } + + return store.keypairs.checkAsync(args.domainKeyPath, 'pem'); + } + // Certificates + , setKeypairAsync: function (args, keypair) { + return store.keypairs.setAsync(args.domainKeyPath, keypair, 'pem'); + } + // Certificates + , checkAsync: function (args) { + if (!args.fullchainPath || !args.privkeyPath || !args.certPath || !args.chainPath) { + return PromiseA.reject(new Error("missing one or more of privkeyPath, fullchainPath, certPath, chainPath from options")); + } + + //, readFileAsync(fullchainPath, 'ascii') + // note: if this ^^ gets added back in, the arrays below must change + return PromiseA.all([ + readFileAsync(args.privkeyPath, 'ascii') // 0 + , readFileAsync(args.certPath, 'ascii') // 1 + , readFileAsync(args.chainPath, 'ascii') // 2 + + // stat the file, not the link + , statAsync(args.certPath) // 3 + ]).then(function (arr) { + return { + privkey: arr[0] // privkey.pem + , cert: arr[1] // cert.pem + , chain: arr[2] // chain.pem + /* + // TODO populate these values only if they are known + , issuedAt: arr[3].mtime.valueOf() + , expiresAt: arr[3].mtime.valueOf() + (90 * 24 * 60 * 60 * 100) + */ + }; + }, function (err) { + if (args.debug) { + log("certificates.check"); + log(err.stack); + } + return null; + }); + } + // Certificates + , setAsync: function (args) { + return store.configs.getAsync(args).then(function (pyobj) { + var pems = args.pems; + + pyobj.checkpoints = parseInt(pyobj.checkpoints, 10) || 0; + + var liveDir = args.liveDir || path.join(args.configDir, 'live', args.domains[0]); + + var certPath = args.certPath || pyobj.cert || path.join(liveDir, 'cert.pem'); + var fullchainPath = args.fullchainPath || pyobj.fullchain || path.join(liveDir, 'fullchain.pem'); + var chainPath = args.chainPath || pyobj.chain || path.join(liveDir, 'chain.pem'); + var privkeyPath = args.privkeyPath || pyobj.privkey || args.domainKeyPath || path.join(liveDir, 'privkey.pem'); + var bundlePath = args.bundlePath || pyobj.bundle || path.join(liveDir, 'bundle.pem'); + + var archiveDir = args.archiveDir || path.join(args.configDir, 'archive', args.domains[0]); + + var checkpoints = pyobj.checkpoints.toString(); + var certArchive = path.join(archiveDir, 'cert' + checkpoints + '.pem'); + var fullchainArchive = path.join(archiveDir, 'fullchain' + checkpoints + '.pem'); + var chainArchive = path.join(archiveDir, 'chain'+ checkpoints + '.pem'); + var privkeyArchive = path.join(archiveDir, 'privkey' + checkpoints + '.pem'); + var bundleArchive = path.join(archiveDir, 'bundle' + checkpoints + '.pem'); + + return mkdirpAsync(archiveDir).then(function () { + return PromiseA.all([ + sfs.writeFileAsync(certArchive, pems.cert, 'ascii') + , sfs.writeFileAsync(chainArchive, pems.chain, 'ascii') + , sfs.writeFileAsync(fullchainArchive, [ pems.cert, pems.chain ].join('\n'), 'ascii') + , sfs.writeFileAsync(privkeyArchive, pems.privkey, 'ascii') + , sfs.writeFileAsync(bundleArchive, pems.bundle, 'ascii') + ]); + }).then(function () { + return mkdirpAsync(liveDir); + }).then(function () { + return PromiseA.all([ + sfs.writeFileAsync(certPath, pems.cert, 'ascii') + , sfs.writeFileAsync(chainPath, pems.chain, 'ascii') + // Most platforms need these two + , sfs.writeFileAsync(fullchainPath, [ pems.cert, pems.chain ].join('\n'), 'ascii') + , sfs.writeFileAsync(privkeyPath, pems.privkey, 'ascii') + // HAProxy needs "bundle.pem" aka "combined.pem" + , sfs.writeFileAsync(bundlePath, [ pems.privkey, pems.cert, pems.chain ].join('\n'), 'ascii') + ]); + }).then(function () { + pyobj.checkpoints += 1; + args.checkpoints += 1; + + // TODO other than for compatibility this is optional, right? + // or is it actually needful for renewal? (i.e. list of domains) + return writeRenewalConfig(args); + }).then(function () { + return { + privkey: pems.privkey + , cert: pems.cert + , chain: pems.chain + , expires: pems.expires + , identifiers: pems.identifiers + + /* + // TODO populate these only if they are actually known + , issuedAt: Date.now() + , expiresAt: Date.now() + (90 * 24 * 60 * 60 * 100) + */ + }; + }); + }); + } + + } + + // + // Accounts + // + , accounts: { + // Accounts + _getAccountKeyPath: function (args) { + var promise = PromiseA.resolve(args.accountId); + + if (args.email && !args.accountKeyPath && !args.accountId) { + promise = store.accounts._getAccountIdByEmail(args); + } + + return promise.then(function (accountId) { + if (!accountId) { + return null; + } + return args.accountKeyPath || path.join(args.accountsDir, accountId, 'private_key.json'); + }); + } + // Accounts + , _getAccountIdByEmail: function (args) { + // If we read 10,000 account directories looking for + // just one email address, that could get crazy. + // We should have a folder per email and list + // each account as a file in the folder + // TODO + var email = args.email; + if ('string' !== typeof email) { + log(args.debug, "No email given"); + return PromiseA.resolve(null); + } + return readdirAsync(args.accountsDir).then(function (nodes) { + log(args.debug, "success reading arg.accountsDir"); + + return PromiseA.all(nodes.map(function (node) { + return readFileAsync(path.join(args.accountsDir, node, 'regr.json'), 'utf8').then(function (text) { + var regr = JSON.parse(text); + regr.__accountId = node; + + return regr; + }); + })).then(function (regrs) { + var accountId; + + log(args.debug, "regrs.length", regrs.length); + + regrs.some(function (regr) { + return regr.body.contact.some(function (contact) { + var match = contact.toLowerCase() === 'mailto:' + email.toLowerCase(); + if (match) { + accountId = regr.__accountId; + return true; + } + }); + }); + + if (!accountId) { + return null; + } + + return accountId; + }); + }).then(function (accountId) { + return accountId; + }, function (err) { + if ('ENOENT' === err.code) { + // ignore error + return null; + } + + return PromiseA.reject(err); + }); + } + // Accounts + , _getAccountIdByPublicKey: function (keypair) { + // we use insecure md5 - even though we know it's bad - because that's how the python client did + var pubkey = keypair.publicKeyPem.replace(/\r/g, ''); + return crypto.createHash('md5').update(pubkey).digest('hex'); + } + // Accounts + , checkKeypairAsync: function (args) { + if (!(args.accountKeyPath || args.accountsDir)) { + return PromiseA.reject(new Error("must provide one of options.accountKeyPath or options.accountsDir")); + } + + return store.accounts._getAccountKeyPath(args).then(function (keypath) { + return store.keypairs.checkAsync(keypath, 'jwk'); + }); + } + // Accounts + , setKeypairAsync: function (args, keypair) { + var accountId; + + if (args.email) { + accountId = store.accounts._getAccountIdByPublicKey(keypair); + } + + return store.accounts._getAccountKeyPath({ + accountsDir: args.accountsDir + , email: args.email + , accountId: args.accountId || accountId + }).then(function (keypath) { + return store.keypairs.setAsync(keypath, keypair, 'jwk'); + }); + } + // Accounts + , checkAsync: function (args) { + var promise; + var files = {}; + var accountId; + + if (args.accountId) { + promise = PromiseA.resolve(args.accountId); + } + else if (args.email) { + promise = store.accounts._getAccountIdByEmail(args); + } + else { + promise = PromiseA.reject(new Error("must provide accountId or email")); + } + + return promise.then(function (_accountId) { + log(args.debug, 'accountId:', _accountId); + if (!_accountId) { + return false; + } + accountId = _accountId; + var accountDir = path.join(args.accountsDir, accountId); + var configs = [ 'meta.json', 'private_key.json', 'regr.json' ]; + + return PromiseA.all(configs.map(function (filename) { + var keyname = filename.slice(0, -5); + + return readFileAsync(path.join(accountDir, filename), 'utf8').then(function (text) { + var data; + + try { + data = JSON.parse(text); + } catch(e) { + files[keyname] = { error: e }; + return; + } + + files[keyname] = data; + + return true; + }, function (err) { + log(args.debug, 'Error reading account files:', err); + files[keyname] = { error: err }; + }); + })); + }).then(function (hasAccount) { + if (!hasAccount) { + return null; + } + var err; + + if (!Object.keys(files).every(function (key) { + return !files[key].error; + }) || !files.private_key || !files.private_key.n) { + err = new Error("Account '" + accountId + "' was corrupt (had id, but was missing files)."); + err.code = 'E_ACCOUNT_CORRUPT'; + err.data = files; + return PromiseA.reject(err); + } + + //files.private_key; + //files.regr; + //files.meta; + files.accountId = accountId; // preserve current account id + files.id = accountId; + files.keypair = { privateKeyJwk: files.private_key }; + + return files; + }); + } + // Accounts + , setAsync: function (args, reg) { + var os = require("os"); + var accountId = store.accounts._getAccountIdByPublicKey(reg.keypair); + var accountDir = path.join(args.accountsDir, accountId); + var accountMeta = { + creation_host: os.hostname() + , creation_dt: new Date().toISOString() + }; + var uri = args.server.replace(/\/directory.*/, + '/acme/reg/' + accountId); + + return mkdirpAsync(accountDir).then(function () { + var regrBody = { + body: reg.receipt, + uri: uri, + }; + + if (typeof reg.newAuthzUrl !== 'undefined') { + regrBody.new_authzr_uri = reg.newAuthzUrl; + } + + // TODO abstract file writing + return PromiseA.all([ + // meta.json {"creation_host": "ns1.redirect-www.org", "creation_dt": "2015-12-11T04:14:38Z"} + writeFileAsync(path.join(accountDir, 'meta.json'), JSON.stringify(accountMeta), 'utf8') + // private_key.json { "e", "d", "n", "q", "p", "kty", "qi", "dp", "dq" } + , writeFileAsync(path.join(accountDir, 'private_key.json'), JSON.stringify(reg.keypair.privateKeyJwk), 'utf8') + // regr.json: + /* + { body: { contact: [ 'mailto:coolaj86@gmail.com' ], + agreement: 'https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf', + key: { e: 'AQAB', kty: 'RSA', n: '...' } }, + uri: 'https://acme-v01.api.letsencrypt.org/acme/reg/71272', + new_authzr_uri: 'https://acme-v01.api.letsencrypt.org/acme/new-authz', + terms_of_service: 'https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf' } + */ + , writeFileAsync(path.join(accountDir, 'regr.json'), + JSON.stringify(regrBody), + 'utf8') + ]); + }).then(function () { + return { + id: accountId + , accountId: accountId + , email: args.email + , keypair: reg.keypair + , receipt: reg.receipt + }; + }); + } + // Accounts + , getAccountIdAsync: function (args) { + var pyconf = promisifyAll(require('pyconf')); + + return pyconf.readFileAsync(args.renewalPath).then(function (renewal) { + var accountId = renewal.account; + renewal = renewal.account; + + return accountId; + }, function (err) { + if ("ENOENT" === err.code) { + return store.accounts._getAccountIdByEmail(args); + } + + return PromiseA.reject(err); + }); + } + } + + // + // Configs + // + , configs: { + // Configs + checkAsync: function (copy) { + copy.domains = []; + + return store.configs._checkHelperAsync(copy).then(function (pyobj) { + var exists = pyobj.checkpoints >= 0; + if (!exists) { + return null; + } + + return pyToJson(pyobj); + }); + } + // Configs + , _checkHelperAsync: function (args) { + var pyconf = promisifyAll(require('pyconf')); + + return pyconf.readFileAsync(args.renewalPath).then(function (pyobj) { + return pyobj; + }, function () { + return pyconf.readFileAsync(path.join(__dirname, 'renewal.conf.tpl')).then(function (pyobj) { + return pyobj; + }); + }); + } + // Configs + , getAsync: function (args) { + return store.configs._checkHelperAsync(args).then(function (pyobj) { + var minver = pyobj.checkpoints >= 0; + + args.pyobj = pyobj; + + if (!minver) { + args.checkpoints = 0; + pyobj.checkpoints = 0; + return writeRenewalConfig(args); + } + + // args.account.id = pyobj.account + // args.configDir = args.configDir || pyobj.configDir; + + args.checkpoints = pyobj.checkpoints; + + args.agreeTos = (args.agreeTos || pyobj.tos) && true; + args.email = args.email || pyobj.email; + args.domains = args.domains || pyobj.domains; + + // yes, it's an array. weird, right? + args.webrootPath = args.webrootPath || pyobj.webrootPath[0]; + args.server = args.server || args.acmeDiscoveryUrl || pyobj.server; + + args.certPath = args.certPath || pyobj.cert; + args.privkeyPath = args.privkeyPath || pyobj.privkey; + args.chainPath = args.chainPath || pyobj.chain; + args.fullchainPath = args.fullchainPath || pyobj.fullchain; + + //, workDir: args.workDir + //, logsDir: args.logsDir + args.rsaKeySize = args.rsaKeySize || pyobj.rsaKeySize; + args.http01Port = args.http01Port || pyobj.http01Port; + args.domainKeyPath = args.domainKeyPath || args.keyPath || pyobj.keyPath; + + return writeRenewalConfig(args); + }); + } + // Configs + , allAsync: function (copy) { + copy.domains = []; + + return readdirAsync(copy.renewalDir).then(function (nodes) { + nodes = nodes.filter(function (node) { + return /^[a-z0-9]+.*\.conf$/.test(node); + }); + + return PromiseA.all(nodes.map(function (node) { + copy.domains = [node.replace(/\.conf$/, '')]; + return store.configs.getAsync(copy); + })); + }); + } + } + + }; + + return store; +}; diff --git a/express-server/node_modules/le-store-certbot/package.json b/express-server/node_modules/le-store-certbot/package.json new file mode 100644 index 00000000..d4dcc5fa --- /dev/null +++ b/express-server/node_modules/le-store-certbot/package.json @@ -0,0 +1,97 @@ +{ + "_args": [ + [ + "le-store-certbot@^2.1.0", + "/nodeapps/https-test/greenlock-express.js" + ] + ], + "_from": "le-store-certbot@>=2.1.0 <3.0.0", + "_hasShrinkwrap": false, + "_id": "le-store-certbot@2.2.1", + "_inCache": true, + "_installable": true, + "_location": "/le-store-certbot", + "_nodeVersion": "10.13.0", + "_npmOperationalInternal": { + "host": "s3://npm-registry-packages", + "tmp": "tmp/le-store-certbot_2.2.1_1541491178195_0.8624656290279973" + }, + "_npmUser": { + "email": "coolaj86@gmail.com", + "name": "coolaj86" + }, + "_npmVersion": "6.4.1", + "_phantomChildren": {}, + "_requested": { + "name": "le-store-certbot", + "raw": "le-store-certbot@^2.1.0", + "rawSpec": "^2.1.0", + "scope": null, + "spec": ">=2.1.0 <3.0.0", + "type": "range" + }, + "_requiredBy": [ + "/", + "/greenlock" + ], + "_resolved": "https://registry.npmjs.org/le-store-certbot/-/le-store-certbot-2.2.1.tgz", + "_shasum": "ee67d89991978855ca7cc8afa1812d2110abdc58", + "_shrinkwrap": null, + "_spec": "le-store-certbot@^2.1.0", + "_where": "/nodeapps/https-test/greenlock-express.js", + "author": { + "email": "coolaj86@gmail.com", + "name": "AJ ONeal", + "url": "https://coolaj86.com/" + }, + "bugs": { + "url": "https://git.coolaj86.com/coolaj86/le-store-certbot.js/issues" + }, + "dependencies": { + "mkdirp": "^0.5.1", + "pyconf": "^1.1.5", + "safe-replace": "^1.0.3" + }, + "description": "The \"certbot\" storage strategy for Greenlock.js", + "devDependencies": {}, + "directories": {}, + "dist": { + "fileCount": 5, + "integrity": "sha512-BhljZjTULhbNBAT6RBiv4TeZegFraMxURYEvh3WRUI048zmXf4ZfC8gwbdu5fnD2tTCsS9fbsCOAQyrFBl4jlA==", + "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb4UnqCRA9TVsSAnZWagAAiSkP/3lBxmMqtnmcqTV6BrRO\ntIeSn7JpBtQ9zdPRNhlze/N4hnUiT677i77fxEXcx3VGTW2qZdvzdgrMQBC/\nT/xxzYA8vqiBSwz94kCGe3dBAjtMm3EqEwteuV1kwyJSAr+rgNjYmnuwNJIL\ngNv0J8/xARH1LDAg+oe02u6frPID71IPDqH+WtvHgsMM4uj4HPsBLZRQKLBq\n32QW+5mbH/LDyqYhWNWWFmJqcXmLOCRtwPIeGbbXM7mCHzjtDBUO05kyzHXs\np07Vac1hpOeIPWsGufKsYY3UOd7pudr/iPhl7bcId6vJjWnGK+UmUQx3zZon\nijdm9haPg9hc3pOYyHV+SKO+1Kw6QHEihEENzWKU551kphlCI2yfI+r7I0vO\nw9IWKWoa5JjTpBoH0mYZ/E3MWNY1KaPZAyW0lKrQhTZ6LHt/8Od8Xx66GqB9\nxZWJNJoxyQMpIqp3AFNQQXdhYCLozBjA7gU4G0EEsXq11gNRoleMGA6vqLKf\n+E3SmDNMpHH0m8he92kBCh6T3BC3V0S3fluq77N4+HHf1vC1wh+k04IRoNNk\n0b6Czg91EdmZsOPtDMN0n5LvWa5WRiBZz0ChhX9BcEidlmzPqVNUY0C1EZYM\nxIiInpD9Bn91ZtH1rya+S21FB5alf5EdfGL6c60WGm3BFDX3D3NLKPrRxOgg\nWr37\r\n=MBXz\r\n-----END PGP SIGNATURE-----\r\n", + "shasum": "ee67d89991978855ca7cc8afa1812d2110abdc58", + "tarball": "https://registry.npmjs.org/le-store-certbot/-/le-store-certbot-2.2.1.tgz", + "unpackedSize": 28707 + }, + "gitHead": "bba58351e44f2f85a857de22472c6f43c94efbf2", + "homepage": "https://git.coolaj86.com/coolaj86/le-store-certbot.js", + "keywords": [ + "certbot", + "le-store", + "le-store-", + "letsencrypt", + "node" + ], + "license": "(MIT OR Apache-2.0)", + "main": "index.js", + "maintainers": [ + { + "name": "coolaj86", + "email": "coolaj86@gmail.com" + } + ], + "name": "le-store-certbot", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "https://git.coolaj86.com/coolaj86/le-store-certbot.js" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "trulyOptionalDependencies": { + "bluebird": "^3.5.1" + }, + "version": "2.2.1" +} diff --git a/express-server/node_modules/le-store-certbot/renewal.conf.tpl b/express-server/node_modules/le-store-certbot/renewal.conf.tpl new file mode 100644 index 00000000..4f1f07f6 --- /dev/null +++ b/express-server/node_modules/le-store-certbot/renewal.conf.tpl @@ -0,0 +1,83 @@ +#cert = :configDir/live/:hostname/cert.pem +cert = :cert_path +privkey = :privkey_path +chain = :chain_path +fullchain = :fullchain_path + +# Options and defaults used in the renewal process +[renewalparams] +no_self_upgrade = True +apache_enmod = a2enmod +no_verify_ssl = False +ifaces = None +apache_dismod = a2dismod +register_unsafely_without_email = False +apache_handle_modules = True +uir = None +installer = None +nginx_ctl = nginx +config_dir = :configDir +text_mode = True +# junk? +# https://github.com/letsencrypt/letsencrypt/issues/1955 +func = +staging = False +prepare = False +work_dir = :work_dir +tos = :agree_tos +init = False +http01_port = :http_01_port +duplicate = False +noninteractive_mode = True +# this is for the domain +key_path = :privkey_path +nginx = False +nginx_server_root = /etc/nginx +fullchain_path = :fullchain_path +email = :email +csr = None +agree_dev_preview = None +redirect = None +verb = certonly +verbose_count = -3 +config_file = None +renew_by_default = True +hsts = False +apache_handle_sites = True +authenticator = webroot +domains = :hostnames #comma,delimited,list +rsa_key_size = :rsa_key_size +apache_challenge_location = /etc/apache2 +# starts at 0 and increments at every renewal +checkpoints = -1 +manual_test_mode = False +apache = False +cert_path = :cert_path +webroot_path = :webroot_paths # comma,delimited,list +reinstall = False +expand = False +strict_permissions = False +apache_server_root = /etc/apache2 +# https://github.com/letsencrypt/letsencrypt/issues/1948 +account = :account_id +dry_run = False +manual_public_ip_logging_ok = False +chain_path = :chain_path +break_my_certs = False +standalone = False +manual = False +server = :acme_discovery_url +standalone_supported_challenges = "http-01,tls-sni-01" +webroot = True +os_packages_only = False +apache_init_script = None +user_agent = None +apache_le_vhost_ext = -le-ssl.conf +debug = False +tls_sni_01_port = 443 +logs_dir = :logs_dir +apache_vhost_root = /etc/apache2/sites-available +configurator = None +must_staple = False +[[webroot_map]] +# :hostname = :webroot_path diff --git a/express-server/node_modules/minimist/.travis.yml b/express-server/node_modules/minimist/.travis.yml new file mode 100644 index 00000000..cc4dba29 --- /dev/null +++ b/express-server/node_modules/minimist/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - "0.8" + - "0.10" diff --git a/express-server/node_modules/minimist/LICENSE b/express-server/node_modules/minimist/LICENSE new file mode 100644 index 00000000..ee27ba4b --- /dev/null +++ b/express-server/node_modules/minimist/LICENSE @@ -0,0 +1,18 @@ +This software is released under the MIT license: + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/express-server/node_modules/minimist/example/parse.js b/express-server/node_modules/minimist/example/parse.js new file mode 100644 index 00000000..abff3e8e --- /dev/null +++ b/express-server/node_modules/minimist/example/parse.js @@ -0,0 +1,2 @@ +var argv = require('../')(process.argv.slice(2)); +console.dir(argv); diff --git a/express-server/node_modules/minimist/index.js b/express-server/node_modules/minimist/index.js new file mode 100644 index 00000000..584f551a --- /dev/null +++ b/express-server/node_modules/minimist/index.js @@ -0,0 +1,187 @@ +module.exports = function (args, opts) { + if (!opts) opts = {}; + + var flags = { bools : {}, strings : {} }; + + [].concat(opts['boolean']).filter(Boolean).forEach(function (key) { + flags.bools[key] = true; + }); + + [].concat(opts.string).filter(Boolean).forEach(function (key) { + flags.strings[key] = true; + }); + + var aliases = {}; + Object.keys(opts.alias || {}).forEach(function (key) { + aliases[key] = [].concat(opts.alias[key]); + aliases[key].forEach(function (x) { + aliases[x] = [key].concat(aliases[key].filter(function (y) { + return x !== y; + })); + }); + }); + + var defaults = opts['default'] || {}; + + var argv = { _ : [] }; + Object.keys(flags.bools).forEach(function (key) { + setArg(key, defaults[key] === undefined ? false : defaults[key]); + }); + + var notFlags = []; + + if (args.indexOf('--') !== -1) { + notFlags = args.slice(args.indexOf('--')+1); + args = args.slice(0, args.indexOf('--')); + } + + function setArg (key, val) { + var value = !flags.strings[key] && isNumber(val) + ? Number(val) : val + ; + setKey(argv, key.split('.'), value); + + (aliases[key] || []).forEach(function (x) { + setKey(argv, x.split('.'), value); + }); + } + + for (var i = 0; i < args.length; i++) { + var arg = args[i]; + + if (/^--.+=/.test(arg)) { + // Using [\s\S] instead of . because js doesn't support the + // 'dotall' regex modifier. See: + // http://stackoverflow.com/a/1068308/13216 + var m = arg.match(/^--([^=]+)=([\s\S]*)$/); + setArg(m[1], m[2]); + } + else if (/^--no-.+/.test(arg)) { + var key = arg.match(/^--no-(.+)/)[1]; + setArg(key, false); + } + else if (/^--.+/.test(arg)) { + var key = arg.match(/^--(.+)/)[1]; + var next = args[i + 1]; + if (next !== undefined && !/^-/.test(next) + && !flags.bools[key] + && (aliases[key] ? !flags.bools[aliases[key]] : true)) { + setArg(key, next); + i++; + } + else if (/^(true|false)$/.test(next)) { + setArg(key, next === 'true'); + i++; + } + else { + setArg(key, flags.strings[key] ? '' : true); + } + } + else if (/^-[^-]+/.test(arg)) { + var letters = arg.slice(1,-1).split(''); + + var broken = false; + for (var j = 0; j < letters.length; j++) { + var next = arg.slice(j+2); + + if (next === '-') { + setArg(letters[j], next) + continue; + } + + if (/[A-Za-z]/.test(letters[j]) + && /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) { + setArg(letters[j], next); + broken = true; + break; + } + + if (letters[j+1] && letters[j+1].match(/\W/)) { + setArg(letters[j], arg.slice(j+2)); + broken = true; + break; + } + else { + setArg(letters[j], flags.strings[letters[j]] ? '' : true); + } + } + + var key = arg.slice(-1)[0]; + if (!broken && key !== '-') { + if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1]) + && !flags.bools[key] + && (aliases[key] ? !flags.bools[aliases[key]] : true)) { + setArg(key, args[i+1]); + i++; + } + else if (args[i+1] && /true|false/.test(args[i+1])) { + setArg(key, args[i+1] === 'true'); + i++; + } + else { + setArg(key, flags.strings[key] ? '' : true); + } + } + } + else { + argv._.push( + flags.strings['_'] || !isNumber(arg) ? arg : Number(arg) + ); + } + } + + Object.keys(defaults).forEach(function (key) { + if (!hasKey(argv, key.split('.'))) { + setKey(argv, key.split('.'), defaults[key]); + + (aliases[key] || []).forEach(function (x) { + setKey(argv, x.split('.'), defaults[key]); + }); + } + }); + + notFlags.forEach(function(key) { + argv._.push(key); + }); + + return argv; +}; + +function hasKey (obj, keys) { + var o = obj; + keys.slice(0,-1).forEach(function (key) { + o = (o[key] || {}); + }); + + var key = keys[keys.length - 1]; + return key in o; +} + +function setKey (obj, keys, value) { + var o = obj; + keys.slice(0,-1).forEach(function (key) { + if (o[key] === undefined) o[key] = {}; + o = o[key]; + }); + + var key = keys[keys.length - 1]; + if (o[key] === undefined || typeof o[key] === 'boolean') { + o[key] = value; + } + else if (Array.isArray(o[key])) { + o[key].push(value); + } + else { + o[key] = [ o[key], value ]; + } +} + +function isNumber (x) { + if (typeof x === 'number') return true; + if (/^0x[0-9a-f]+$/i.test(x)) return true; + return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x); +} + +function longest (xs) { + return Math.max.apply(null, xs.map(function (x) { return x.length })); +} diff --git a/express-server/node_modules/minimist/package.json b/express-server/node_modules/minimist/package.json new file mode 100644 index 00000000..763d37d3 --- /dev/null +++ b/express-server/node_modules/minimist/package.json @@ -0,0 +1,93 @@ +{ + "_args": [ + [ + "minimist@0.0.8", + "/nodeapps/https-test/greenlock-express.js/node_modules/mkdirp" + ] + ], + "_from": "minimist@0.0.8", + "_id": "minimist@0.0.8", + "_inCache": true, + "_installable": true, + "_location": "/minimist", + "_npmUser": { + "email": "mail@substack.net", + "name": "substack" + }, + "_npmVersion": "1.4.3", + "_phantomChildren": {}, + "_requested": { + "name": "minimist", + "raw": "minimist@0.0.8", + "rawSpec": "0.0.8", + "scope": null, + "spec": "0.0.8", + "type": "version" + }, + "_requiredBy": [ + "/mkdirp" + ], + "_resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "_shasum": "857fcabfc3397d2625b8228262e86aa7a011b05d", + "_shrinkwrap": null, + "_spec": "minimist@0.0.8", + "_where": "/nodeapps/https-test/greenlock-express.js/node_modules/mkdirp", + "author": { + "email": "mail@substack.net", + "name": "James Halliday", + "url": "http://substack.net" + }, + "bugs": { + "url": "https://github.com/substack/minimist/issues" + }, + "dependencies": {}, + "description": "parse argument options", + "devDependencies": { + "tap": "~0.4.0", + "tape": "~1.0.4" + }, + "directories": {}, + "dist": { + "shasum": "857fcabfc3397d2625b8228262e86aa7a011b05d", + "tarball": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" + }, + "homepage": "https://github.com/substack/minimist", + "keywords": [ + "argv", + "getopt", + "optimist", + "parser" + ], + "license": "MIT", + "main": "index.js", + "maintainers": [ + { + "name": "substack", + "email": "mail@substack.net" + } + ], + "name": "minimist", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/substack/minimist.git" + }, + "scripts": { + "test": "tap test/*.js" + }, + "testling": { + "browsers": [ + "chrome/10", + "chrome/latest", + "ff/5", + "firefox/latest", + "ie/6..latest", + "opera/12", + "safari/5.1", + "safari/latest" + ], + "files": "test/*.js" + }, + "version": "0.0.8" +} diff --git a/express-server/node_modules/minimist/readme.markdown b/express-server/node_modules/minimist/readme.markdown new file mode 100644 index 00000000..c2563532 --- /dev/null +++ b/express-server/node_modules/minimist/readme.markdown @@ -0,0 +1,73 @@ +# minimist + +parse argument options + +This module is the guts of optimist's argument parser without all the +fanciful decoration. + +[![browser support](https://ci.testling.com/substack/minimist.png)](http://ci.testling.com/substack/minimist) + +[![build status](https://secure.travis-ci.org/substack/minimist.png)](http://travis-ci.org/substack/minimist) + +# example + +``` js +var argv = require('minimist')(process.argv.slice(2)); +console.dir(argv); +``` + +``` +$ node example/parse.js -a beep -b boop +{ _: [], a: 'beep', b: 'boop' } +``` + +``` +$ node example/parse.js -x 3 -y 4 -n5 -abc --beep=boop foo bar baz +{ _: [ 'foo', 'bar', 'baz' ], + x: 3, + y: 4, + n: 5, + a: true, + b: true, + c: true, + beep: 'boop' } +``` + +# methods + +``` js +var parseArgs = require('minimist') +``` + +## var argv = parseArgs(args, opts={}) + +Return an argument object `argv` populated with the array arguments from `args`. + +`argv._` contains all the arguments that didn't have an option associated with +them. + +Numeric-looking arguments will be returned as numbers unless `opts.string` or +`opts.boolean` is set for that argument name. + +Any arguments after `'--'` will not be parsed and will end up in `argv._`. + +options can be: + +* `opts.string` - a string or array of strings argument names to always treat as +strings +* `opts.boolean` - a string or array of strings to always treat as booleans +* `opts.alias` - an object mapping string names to strings or arrays of string +argument names to use as aliases +* `opts.default` - an object mapping string argument names to default values + +# install + +With [npm](https://npmjs.org) do: + +``` +npm install minimist +``` + +# license + +MIT diff --git a/express-server/node_modules/minimist/test/dash.js b/express-server/node_modules/minimist/test/dash.js new file mode 100644 index 00000000..8b034b99 --- /dev/null +++ b/express-server/node_modules/minimist/test/dash.js @@ -0,0 +1,24 @@ +var parse = require('../'); +var test = require('tape'); + +test('-', function (t) { + t.plan(5); + t.deepEqual(parse([ '-n', '-' ]), { n: '-', _: [] }); + t.deepEqual(parse([ '-' ]), { _: [ '-' ] }); + t.deepEqual(parse([ '-f-' ]), { f: '-', _: [] }); + t.deepEqual( + parse([ '-b', '-' ], { boolean: 'b' }), + { b: true, _: [ '-' ] } + ); + t.deepEqual( + parse([ '-s', '-' ], { string: 's' }), + { s: '-', _: [] } + ); +}); + +test('-a -- b', function (t) { + t.plan(3); + t.deepEqual(parse([ '-a', '--', 'b' ]), { a: true, _: [ 'b' ] }); + t.deepEqual(parse([ '--a', '--', 'b' ]), { a: true, _: [ 'b' ] }); + t.deepEqual(parse([ '--a', '--', 'b' ]), { a: true, _: [ 'b' ] }); +}); diff --git a/express-server/node_modules/minimist/test/default_bool.js b/express-server/node_modules/minimist/test/default_bool.js new file mode 100644 index 00000000..f0041ee4 --- /dev/null +++ b/express-server/node_modules/minimist/test/default_bool.js @@ -0,0 +1,20 @@ +var test = require('tape'); +var parse = require('../'); + +test('boolean default true', function (t) { + var argv = parse([], { + boolean: 'sometrue', + default: { sometrue: true } + }); + t.equal(argv.sometrue, true); + t.end(); +}); + +test('boolean default false', function (t) { + var argv = parse([], { + boolean: 'somefalse', + default: { somefalse: false } + }); + t.equal(argv.somefalse, false); + t.end(); +}); diff --git a/express-server/node_modules/minimist/test/dotted.js b/express-server/node_modules/minimist/test/dotted.js new file mode 100644 index 00000000..ef0ae349 --- /dev/null +++ b/express-server/node_modules/minimist/test/dotted.js @@ -0,0 +1,16 @@ +var parse = require('../'); +var test = require('tape'); + +test('dotted alias', function (t) { + var argv = parse(['--a.b', '22'], {default: {'a.b': 11}, alias: {'a.b': 'aa.bb'}}); + t.equal(argv.a.b, 22); + t.equal(argv.aa.bb, 22); + t.end(); +}); + +test('dotted default', function (t) { + var argv = parse('', {default: {'a.b': 11}, alias: {'a.b': 'aa.bb'}}); + t.equal(argv.a.b, 11); + t.equal(argv.aa.bb, 11); + t.end(); +}); diff --git a/express-server/node_modules/minimist/test/long.js b/express-server/node_modules/minimist/test/long.js new file mode 100644 index 00000000..5d3a1e09 --- /dev/null +++ b/express-server/node_modules/minimist/test/long.js @@ -0,0 +1,31 @@ +var test = require('tape'); +var parse = require('../'); + +test('long opts', function (t) { + t.deepEqual( + parse([ '--bool' ]), + { bool : true, _ : [] }, + 'long boolean' + ); + t.deepEqual( + parse([ '--pow', 'xixxle' ]), + { pow : 'xixxle', _ : [] }, + 'long capture sp' + ); + t.deepEqual( + parse([ '--pow=xixxle' ]), + { pow : 'xixxle', _ : [] }, + 'long capture eq' + ); + t.deepEqual( + parse([ '--host', 'localhost', '--port', '555' ]), + { host : 'localhost', port : 555, _ : [] }, + 'long captures sp' + ); + t.deepEqual( + parse([ '--host=localhost', '--port=555' ]), + { host : 'localhost', port : 555, _ : [] }, + 'long captures eq' + ); + t.end(); +}); diff --git a/express-server/node_modules/minimist/test/parse.js b/express-server/node_modules/minimist/test/parse.js new file mode 100644 index 00000000..8a906466 --- /dev/null +++ b/express-server/node_modules/minimist/test/parse.js @@ -0,0 +1,318 @@ +var parse = require('../'); +var test = require('tape'); + +test('parse args', function (t) { + t.deepEqual( + parse([ '--no-moo' ]), + { moo : false, _ : [] }, + 'no' + ); + t.deepEqual( + parse([ '-v', 'a', '-v', 'b', '-v', 'c' ]), + { v : ['a','b','c'], _ : [] }, + 'multi' + ); + t.end(); +}); + +test('comprehensive', function (t) { + t.deepEqual( + parse([ + '--name=meowmers', 'bare', '-cats', 'woo', + '-h', 'awesome', '--multi=quux', + '--key', 'value', + '-b', '--bool', '--no-meep', '--multi=baz', + '--', '--not-a-flag', 'eek' + ]), + { + c : true, + a : true, + t : true, + s : 'woo', + h : 'awesome', + b : true, + bool : true, + key : 'value', + multi : [ 'quux', 'baz' ], + meep : false, + name : 'meowmers', + _ : [ 'bare', '--not-a-flag', 'eek' ] + } + ); + t.end(); +}); + +test('nums', function (t) { + var argv = parse([ + '-x', '1234', + '-y', '5.67', + '-z', '1e7', + '-w', '10f', + '--hex', '0xdeadbeef', + '789' + ]); + t.deepEqual(argv, { + x : 1234, + y : 5.67, + z : 1e7, + w : '10f', + hex : 0xdeadbeef, + _ : [ 789 ] + }); + t.deepEqual(typeof argv.x, 'number'); + t.deepEqual(typeof argv.y, 'number'); + t.deepEqual(typeof argv.z, 'number'); + t.deepEqual(typeof argv.w, 'string'); + t.deepEqual(typeof argv.hex, 'number'); + t.deepEqual(typeof argv._[0], 'number'); + t.end(); +}); + +test('flag boolean', function (t) { + var argv = parse([ '-t', 'moo' ], { boolean: 't' }); + t.deepEqual(argv, { t : true, _ : [ 'moo' ] }); + t.deepEqual(typeof argv.t, 'boolean'); + t.end(); +}); + +test('flag boolean value', function (t) { + var argv = parse(['--verbose', 'false', 'moo', '-t', 'true'], { + boolean: [ 't', 'verbose' ], + default: { verbose: true } + }); + + t.deepEqual(argv, { + verbose: false, + t: true, + _: ['moo'] + }); + + t.deepEqual(typeof argv.verbose, 'boolean'); + t.deepEqual(typeof argv.t, 'boolean'); + t.end(); +}); + +test('flag boolean default false', function (t) { + var argv = parse(['moo'], { + boolean: ['t', 'verbose'], + default: { verbose: false, t: false } + }); + + t.deepEqual(argv, { + verbose: false, + t: false, + _: ['moo'] + }); + + t.deepEqual(typeof argv.verbose, 'boolean'); + t.deepEqual(typeof argv.t, 'boolean'); + t.end(); + +}); + +test('boolean groups', function (t) { + var argv = parse([ '-x', '-z', 'one', 'two', 'three' ], { + boolean: ['x','y','z'] + }); + + t.deepEqual(argv, { + x : true, + y : false, + z : true, + _ : [ 'one', 'two', 'three' ] + }); + + t.deepEqual(typeof argv.x, 'boolean'); + t.deepEqual(typeof argv.y, 'boolean'); + t.deepEqual(typeof argv.z, 'boolean'); + t.end(); +}); + +test('newlines in params' , function (t) { + var args = parse([ '-s', "X\nX" ]) + t.deepEqual(args, { _ : [], s : "X\nX" }); + + // reproduce in bash: + // VALUE="new + // line" + // node program.js --s="$VALUE" + args = parse([ "--s=X\nX" ]) + t.deepEqual(args, { _ : [], s : "X\nX" }); + t.end(); +}); + +test('strings' , function (t) { + var s = parse([ '-s', '0001234' ], { string: 's' }).s; + t.equal(s, '0001234'); + t.equal(typeof s, 'string'); + + var x = parse([ '-x', '56' ], { string: 'x' }).x; + t.equal(x, '56'); + t.equal(typeof x, 'string'); + t.end(); +}); + +test('stringArgs', function (t) { + var s = parse([ ' ', ' ' ], { string: '_' })._; + t.same(s.length, 2); + t.same(typeof s[0], 'string'); + t.same(s[0], ' '); + t.same(typeof s[1], 'string'); + t.same(s[1], ' '); + t.end(); +}); + +test('empty strings', function(t) { + var s = parse([ '-s' ], { string: 's' }).s; + t.equal(s, ''); + t.equal(typeof s, 'string'); + + var str = parse([ '--str' ], { string: 'str' }).str; + t.equal(str, ''); + t.equal(typeof str, 'string'); + + var letters = parse([ '-art' ], { + string: [ 'a', 't' ] + }); + + t.equal(letters.a, ''); + t.equal(letters.r, true); + t.equal(letters.t, ''); + + t.end(); +}); + + +test('slashBreak', function (t) { + t.same( + parse([ '-I/foo/bar/baz' ]), + { I : '/foo/bar/baz', _ : [] } + ); + t.same( + parse([ '-xyz/foo/bar/baz' ]), + { x : true, y : true, z : '/foo/bar/baz', _ : [] } + ); + t.end(); +}); + +test('alias', function (t) { + var argv = parse([ '-f', '11', '--zoom', '55' ], { + alias: { z: 'zoom' } + }); + t.equal(argv.zoom, 55); + t.equal(argv.z, argv.zoom); + t.equal(argv.f, 11); + t.end(); +}); + +test('multiAlias', function (t) { + var argv = parse([ '-f', '11', '--zoom', '55' ], { + alias: { z: [ 'zm', 'zoom' ] } + }); + t.equal(argv.zoom, 55); + t.equal(argv.z, argv.zoom); + t.equal(argv.z, argv.zm); + t.equal(argv.f, 11); + t.end(); +}); + +test('nested dotted objects', function (t) { + var argv = parse([ + '--foo.bar', '3', '--foo.baz', '4', + '--foo.quux.quibble', '5', '--foo.quux.o_O', + '--beep.boop' + ]); + + t.same(argv.foo, { + bar : 3, + baz : 4, + quux : { + quibble : 5, + o_O : true + } + }); + t.same(argv.beep, { boop : true }); + t.end(); +}); + +test('boolean and alias with chainable api', function (t) { + var aliased = [ '-h', 'derp' ]; + var regular = [ '--herp', 'derp' ]; + var opts = { + herp: { alias: 'h', boolean: true } + }; + var aliasedArgv = parse(aliased, { + boolean: 'herp', + alias: { h: 'herp' } + }); + var propertyArgv = parse(regular, { + boolean: 'herp', + alias: { h: 'herp' } + }); + var expected = { + herp: true, + h: true, + '_': [ 'derp' ] + }; + + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.end(); +}); + +test('boolean and alias with options hash', function (t) { + var aliased = [ '-h', 'derp' ]; + var regular = [ '--herp', 'derp' ]; + var opts = { + alias: { 'h': 'herp' }, + boolean: 'herp' + }; + var aliasedArgv = parse(aliased, opts); + var propertyArgv = parse(regular, opts); + var expected = { + herp: true, + h: true, + '_': [ 'derp' ] + }; + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.end(); +}); + +test('boolean and alias using explicit true', function (t) { + var aliased = [ '-h', 'true' ]; + var regular = [ '--herp', 'true' ]; + var opts = { + alias: { h: 'herp' }, + boolean: 'h' + }; + var aliasedArgv = parse(aliased, opts); + var propertyArgv = parse(regular, opts); + var expected = { + herp: true, + h: true, + '_': [ ] + }; + + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.end(); +}); + +// regression, see https://github.com/substack/node-optimist/issues/71 +test('boolean and --x=true', function(t) { + var parsed = parse(['--boool', '--other=true'], { + boolean: 'boool' + }); + + t.same(parsed.boool, true); + t.same(parsed.other, 'true'); + + parsed = parse(['--boool', '--other=false'], { + boolean: 'boool' + }); + + t.same(parsed.boool, true); + t.same(parsed.other, 'false'); + t.end(); +}); diff --git a/express-server/node_modules/minimist/test/parse_modified.js b/express-server/node_modules/minimist/test/parse_modified.js new file mode 100644 index 00000000..21851b03 --- /dev/null +++ b/express-server/node_modules/minimist/test/parse_modified.js @@ -0,0 +1,9 @@ +var parse = require('../'); +var test = require('tape'); + +test('parse with modifier functions' , function (t) { + t.plan(1); + + var argv = parse([ '-b', '123' ], { boolean: 'b' }); + t.deepEqual(argv, { b: true, _: ['123'] }); +}); diff --git a/express-server/node_modules/minimist/test/short.js b/express-server/node_modules/minimist/test/short.js new file mode 100644 index 00000000..d513a1c2 --- /dev/null +++ b/express-server/node_modules/minimist/test/short.js @@ -0,0 +1,67 @@ +var parse = require('../'); +var test = require('tape'); + +test('numeric short args', function (t) { + t.plan(2); + t.deepEqual(parse([ '-n123' ]), { n: 123, _: [] }); + t.deepEqual( + parse([ '-123', '456' ]), + { 1: true, 2: true, 3: 456, _: [] } + ); +}); + +test('short', function (t) { + t.deepEqual( + parse([ '-b' ]), + { b : true, _ : [] }, + 'short boolean' + ); + t.deepEqual( + parse([ 'foo', 'bar', 'baz' ]), + { _ : [ 'foo', 'bar', 'baz' ] }, + 'bare' + ); + t.deepEqual( + parse([ '-cats' ]), + { c : true, a : true, t : true, s : true, _ : [] }, + 'group' + ); + t.deepEqual( + parse([ '-cats', 'meow' ]), + { c : true, a : true, t : true, s : 'meow', _ : [] }, + 'short group next' + ); + t.deepEqual( + parse([ '-h', 'localhost' ]), + { h : 'localhost', _ : [] }, + 'short capture' + ); + t.deepEqual( + parse([ '-h', 'localhost', '-p', '555' ]), + { h : 'localhost', p : 555, _ : [] }, + 'short captures' + ); + t.end(); +}); + +test('mixed short bool and capture', function (t) { + t.same( + parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]), + { + f : true, p : 555, h : 'localhost', + _ : [ 'script.js' ] + } + ); + t.end(); +}); + +test('short and long', function (t) { + t.deepEqual( + parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]), + { + f : true, p : 555, h : 'localhost', + _ : [ 'script.js' ] + } + ); + t.end(); +}); diff --git a/express-server/node_modules/minimist/test/whitespace.js b/express-server/node_modules/minimist/test/whitespace.js new file mode 100644 index 00000000..8a52a58c --- /dev/null +++ b/express-server/node_modules/minimist/test/whitespace.js @@ -0,0 +1,8 @@ +var parse = require('../'); +var test = require('tape'); + +test('whitespace should be whitespace' , function (t) { + t.plan(1); + var x = parse([ '-x', '\t' ]).x; + t.equal(x, '\t'); +}); diff --git a/express-server/node_modules/mkdirp/.travis.yml b/express-server/node_modules/mkdirp/.travis.yml new file mode 100644 index 00000000..74c57bf1 --- /dev/null +++ b/express-server/node_modules/mkdirp/.travis.yml @@ -0,0 +1,8 @@ +language: node_js +node_js: + - "0.8" + - "0.10" + - "0.12" + - "iojs" +before_install: + - npm install -g npm@~1.4.6 diff --git a/express-server/node_modules/mkdirp/LICENSE b/express-server/node_modules/mkdirp/LICENSE new file mode 100644 index 00000000..432d1aeb --- /dev/null +++ b/express-server/node_modules/mkdirp/LICENSE @@ -0,0 +1,21 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/express-server/node_modules/mkdirp/bin/cmd.js b/express-server/node_modules/mkdirp/bin/cmd.js new file mode 100644 index 00000000..d95de15a --- /dev/null +++ b/express-server/node_modules/mkdirp/bin/cmd.js @@ -0,0 +1,33 @@ +#!/usr/bin/env node + +var mkdirp = require('../'); +var minimist = require('minimist'); +var fs = require('fs'); + +var argv = minimist(process.argv.slice(2), { + alias: { m: 'mode', h: 'help' }, + string: [ 'mode' ] +}); +if (argv.help) { + fs.createReadStream(__dirname + '/usage.txt').pipe(process.stdout); + return; +} + +var paths = argv._.slice(); +var mode = argv.mode ? parseInt(argv.mode, 8) : undefined; + +(function next () { + if (paths.length === 0) return; + var p = paths.shift(); + + if (mode === undefined) mkdirp(p, cb) + else mkdirp(p, mode, cb) + + function cb (err) { + if (err) { + console.error(err.message); + process.exit(1); + } + else next(); + } +})(); diff --git a/express-server/node_modules/mkdirp/bin/usage.txt b/express-server/node_modules/mkdirp/bin/usage.txt new file mode 100644 index 00000000..f952aa2c --- /dev/null +++ b/express-server/node_modules/mkdirp/bin/usage.txt @@ -0,0 +1,12 @@ +usage: mkdirp [DIR1,DIR2..] {OPTIONS} + + Create each supplied directory including any necessary parent directories that + don't yet exist. + + If the directory already exists, do nothing. + +OPTIONS are: + + -m, --mode If a directory needs to be created, set the mode as an octal + permission string. + diff --git a/express-server/node_modules/mkdirp/examples/pow.js b/express-server/node_modules/mkdirp/examples/pow.js new file mode 100644 index 00000000..e6924212 --- /dev/null +++ b/express-server/node_modules/mkdirp/examples/pow.js @@ -0,0 +1,6 @@ +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') +}); diff --git a/express-server/node_modules/mkdirp/index.js b/express-server/node_modules/mkdirp/index.js new file mode 100644 index 00000000..6ce241b5 --- /dev/null +++ b/express-server/node_modules/mkdirp/index.js @@ -0,0 +1,98 @@ +var path = require('path'); +var fs = require('fs'); +var _0777 = parseInt('0777', 8); + +module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; + +function mkdirP (p, opts, f, made) { + if (typeof opts === 'function') { + f = opts; + opts = {}; + } + else if (!opts || typeof opts !== 'object') { + opts = { mode: opts }; + } + + var mode = opts.mode; + var xfs = opts.fs || fs; + + if (mode === undefined) { + mode = _0777 & (~process.umask()); + } + if (!made) made = null; + + var cb = f || function () {}; + p = path.resolve(p); + + xfs.mkdir(p, mode, function (er) { + if (!er) { + made = made || p; + return cb(null, made); + } + switch (er.code) { + case 'ENOENT': + mkdirP(path.dirname(p), opts, function (er, made) { + if (er) cb(er, made); + else mkdirP(p, opts, cb, made); + }); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + xfs.stat(p, function (er2, stat) { + // if the stat fails, then that's super weird. + // let the original error be the failure reason. + if (er2 || !stat.isDirectory()) cb(er, made) + else cb(null, made); + }); + break; + } + }); +} + +mkdirP.sync = function sync (p, opts, made) { + if (!opts || typeof opts !== 'object') { + opts = { mode: opts }; + } + + var mode = opts.mode; + var xfs = opts.fs || fs; + + if (mode === undefined) { + mode = _0777 & (~process.umask()); + } + if (!made) made = null; + + p = path.resolve(p); + + try { + xfs.mkdirSync(p, mode); + made = made || p; + } + catch (err0) { + switch (err0.code) { + case 'ENOENT' : + made = sync(path.dirname(p), opts, made); + sync(p, opts, made); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + var stat; + try { + stat = xfs.statSync(p); + } + catch (err1) { + throw err0; + } + if (!stat.isDirectory()) throw err0; + break; + } + } + + return made; +}; diff --git a/express-server/node_modules/mkdirp/package.json b/express-server/node_modules/mkdirp/package.json new file mode 100644 index 00000000..c80a46b3 --- /dev/null +++ b/express-server/node_modules/mkdirp/package.json @@ -0,0 +1,86 @@ +{ + "_args": [ + [ + "mkdirp@^0.5.1", + "/nodeapps/https-test/greenlock-express.js/node_modules/le-challenge-fs" + ] + ], + "_from": "mkdirp@>=0.5.1 <0.6.0", + "_id": "mkdirp@0.5.1", + "_inCache": true, + "_installable": true, + "_location": "/mkdirp", + "_nodeVersion": "2.0.0", + "_npmUser": { + "email": "substack@gmail.com", + "name": "substack" + }, + "_npmVersion": "2.9.0", + "_phantomChildren": {}, + "_requested": { + "name": "mkdirp", + "raw": "mkdirp@^0.5.1", + "rawSpec": "^0.5.1", + "scope": null, + "spec": ">=0.5.1 <0.6.0", + "type": "range" + }, + "_requiredBy": [ + "/le-challenge-fs", + "/le-store-certbot" + ], + "_resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "_shasum": "30057438eac6cf7f8c4767f38648d6697d75c903", + "_shrinkwrap": null, + "_spec": "mkdirp@^0.5.1", + "_where": "/nodeapps/https-test/greenlock-express.js/node_modules/le-challenge-fs", + "author": { + "email": "mail@substack.net", + "name": "James Halliday", + "url": "http://substack.net" + }, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "bugs": { + "url": "https://github.com/substack/node-mkdirp/issues" + }, + "dependencies": { + "minimist": "0.0.8" + }, + "description": "Recursively mkdir, like `mkdir -p`", + "devDependencies": { + "mock-fs": "2 >=2.7.0", + "tap": "1" + }, + "directories": {}, + "dist": { + "shasum": "30057438eac6cf7f8c4767f38648d6697d75c903", + "tarball": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz" + }, + "gitHead": "d4eff0f06093aed4f387e88e9fc301cb76beedc7", + "homepage": "https://github.com/substack/node-mkdirp#readme", + "keywords": [ + "directory", + "mkdir" + ], + "license": "MIT", + "main": "index.js", + "maintainers": [ + { + "name": "substack", + "email": "mail@substack.net" + } + ], + "name": "mkdirp", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/substack/node-mkdirp.git" + }, + "scripts": { + "test": "tap test/*.js" + }, + "version": "0.5.1" +} diff --git a/express-server/node_modules/mkdirp/readme.markdown b/express-server/node_modules/mkdirp/readme.markdown new file mode 100644 index 00000000..3cc13153 --- /dev/null +++ b/express-server/node_modules/mkdirp/readme.markdown @@ -0,0 +1,100 @@ +# mkdirp + +Like `mkdir -p`, but in node.js! + +[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp) + +# example + +## pow.js + +```js +var mkdirp = require('mkdirp'); + +mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') +}); +``` + +Output + +``` +pow! +``` + +And now /tmp/foo/bar/baz exists, huzzah! + +# methods + +```js +var mkdirp = require('mkdirp'); +``` + +## mkdirp(dir, opts, cb) + +Create a new directory and any necessary subdirectories at `dir` with octal +permission string `opts.mode`. If `opts` is a non-object, it will be treated as +the `opts.mode`. + +If `opts.mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +`cb(err, made)` fires with the error or the first directory `made` +that had to be created, if any. + +You can optionally pass in an alternate `fs` implementation by passing in +`opts.fs`. Your implementation should have `opts.fs.mkdir(path, mode, cb)` and +`opts.fs.stat(path, cb)`. + +## mkdirp.sync(dir, opts) + +Synchronously create a new directory and any necessary subdirectories at `dir` +with octal permission string `opts.mode`. If `opts` is a non-object, it will be +treated as the `opts.mode`. + +If `opts.mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +Returns the first directory that had to be created, if any. + +You can optionally pass in an alternate `fs` implementation by passing in +`opts.fs`. Your implementation should have `opts.fs.mkdirSync(path, mode)` and +`opts.fs.statSync(path)`. + +# usage + +This package also ships with a `mkdirp` command. + +``` +usage: mkdirp [DIR1,DIR2..] {OPTIONS} + + Create each supplied directory including any necessary parent directories that + don't yet exist. + + If the directory already exists, do nothing. + +OPTIONS are: + + -m, --mode If a directory needs to be created, set the mode as an octal + permission string. + +``` + +# install + +With [npm](http://npmjs.org) do: + +``` +npm install mkdirp +``` + +to get the library, or + +``` +npm install -g mkdirp +``` + +to get the command. + +# license + +MIT diff --git a/express-server/node_modules/mkdirp/test/chmod.js b/express-server/node_modules/mkdirp/test/chmod.js new file mode 100644 index 00000000..6a404b93 --- /dev/null +++ b/express-server/node_modules/mkdirp/test/chmod.js @@ -0,0 +1,41 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; +var _0777 = parseInt('0777', 8); +var _0755 = parseInt('0755', 8); +var _0744 = parseInt('0744', 8); + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +test('chmod-pre', function (t) { + var mode = _0744 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.equal(stat && stat.mode & _0777, mode, 'should be 0744'); + t.end(); + }); + }); +}); + +test('chmod', function (t) { + var mode = _0755 + mkdirp(file, mode, function (er) { + t.ifError(er, 'should not error'); + fs.stat(file, function (er, stat) { + t.ifError(er, 'should exist'); + t.ok(stat && stat.isDirectory(), 'should be directory'); + t.end(); + }); + }); +}); diff --git a/express-server/node_modules/mkdirp/test/clobber.js b/express-server/node_modules/mkdirp/test/clobber.js new file mode 100644 index 00000000..2433b9ad --- /dev/null +++ b/express-server/node_modules/mkdirp/test/clobber.js @@ -0,0 +1,38 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; +var _0755 = parseInt('0755', 8); + +var ps = [ '', 'tmp' ]; + +for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); +} + +var file = ps.join('/'); + +// a file in the way +var itw = ps.slice(0, 3).join('/'); + + +test('clobber-pre', function (t) { + console.error("about to write to "+itw) + fs.writeFileSync(itw, 'I AM IN THE WAY, THE TRUTH, AND THE LIGHT.'); + + fs.stat(itw, function (er, stat) { + t.ifError(er) + t.ok(stat && stat.isFile(), 'should be file') + t.end() + }) +}) + +test('clobber', function (t) { + t.plan(2); + mkdirp(file, _0755, function (err) { + t.ok(err); + t.equal(err.code, 'ENOTDIR'); + t.end(); + }); +}); diff --git a/express-server/node_modules/mkdirp/test/mkdirp.js b/express-server/node_modules/mkdirp/test/mkdirp.js new file mode 100644 index 00000000..eaa8921c --- /dev/null +++ b/express-server/node_modules/mkdirp/test/mkdirp.js @@ -0,0 +1,28 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var exists = fs.exists || path.exists; +var test = require('tap').test; +var _0777 = parseInt('0777', 8); +var _0755 = parseInt('0755', 8); + +test('woo', function (t) { + t.plan(5); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, _0755, function (err) { + t.ifError(err); + exists(file, function (ex) { + t.ok(ex, 'file created'); + fs.stat(file, function (err, stat) { + t.ifError(err); + t.equal(stat.mode & _0777, _0755); + t.ok(stat.isDirectory(), 'target not a directory'); + }) + }) + }); +}); diff --git a/express-server/node_modules/mkdirp/test/opts_fs.js b/express-server/node_modules/mkdirp/test/opts_fs.js new file mode 100644 index 00000000..97186b62 --- /dev/null +++ b/express-server/node_modules/mkdirp/test/opts_fs.js @@ -0,0 +1,29 @@ +var mkdirp = require('../'); +var path = require('path'); +var test = require('tap').test; +var mockfs = require('mock-fs'); +var _0777 = parseInt('0777', 8); +var _0755 = parseInt('0755', 8); + +test('opts.fs', function (t) { + t.plan(5); + + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/beep/boop/' + [x,y,z].join('/'); + var xfs = mockfs.fs(); + + mkdirp(file, { fs: xfs, mode: _0755 }, function (err) { + t.ifError(err); + xfs.exists(file, function (ex) { + t.ok(ex, 'created file'); + xfs.stat(file, function (err, stat) { + t.ifError(err); + t.equal(stat.mode & _0777, _0755); + t.ok(stat.isDirectory(), 'target not a directory'); + }); + }); + }); +}); diff --git a/express-server/node_modules/mkdirp/test/opts_fs_sync.js b/express-server/node_modules/mkdirp/test/opts_fs_sync.js new file mode 100644 index 00000000..6c370aa6 --- /dev/null +++ b/express-server/node_modules/mkdirp/test/opts_fs_sync.js @@ -0,0 +1,27 @@ +var mkdirp = require('../'); +var path = require('path'); +var test = require('tap').test; +var mockfs = require('mock-fs'); +var _0777 = parseInt('0777', 8); +var _0755 = parseInt('0755', 8); + +test('opts.fs sync', function (t) { + t.plan(4); + + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/beep/boop/' + [x,y,z].join('/'); + var xfs = mockfs.fs(); + + mkdirp.sync(file, { fs: xfs, mode: _0755 }); + xfs.exists(file, function (ex) { + t.ok(ex, 'created file'); + xfs.stat(file, function (err, stat) { + t.ifError(err); + t.equal(stat.mode & _0777, _0755); + t.ok(stat.isDirectory(), 'target not a directory'); + }); + }); +}); diff --git a/express-server/node_modules/mkdirp/test/perm.js b/express-server/node_modules/mkdirp/test/perm.js new file mode 100644 index 00000000..fbce44b8 --- /dev/null +++ b/express-server/node_modules/mkdirp/test/perm.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var exists = fs.exists || path.exists; +var test = require('tap').test; +var _0777 = parseInt('0777', 8); +var _0755 = parseInt('0755', 8); + +test('async perm', function (t) { + t.plan(5); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16); + + mkdirp(file, _0755, function (err) { + t.ifError(err); + exists(file, function (ex) { + t.ok(ex, 'file created'); + fs.stat(file, function (err, stat) { + t.ifError(err); + t.equal(stat.mode & _0777, _0755); + t.ok(stat.isDirectory(), 'target not a directory'); + }) + }) + }); +}); + +test('async root perm', function (t) { + mkdirp('/tmp', _0755, function (err) { + if (err) t.fail(err); + t.end(); + }); + t.end(); +}); diff --git a/express-server/node_modules/mkdirp/test/perm_sync.js b/express-server/node_modules/mkdirp/test/perm_sync.js new file mode 100644 index 00000000..398229fe --- /dev/null +++ b/express-server/node_modules/mkdirp/test/perm_sync.js @@ -0,0 +1,36 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var exists = fs.exists || path.exists; +var test = require('tap').test; +var _0777 = parseInt('0777', 8); +var _0755 = parseInt('0755', 8); + +test('sync perm', function (t) { + t.plan(4); + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json'; + + mkdirp.sync(file, _0755); + exists(file, function (ex) { + t.ok(ex, 'file created'); + fs.stat(file, function (err, stat) { + t.ifError(err); + t.equal(stat.mode & _0777, _0755); + t.ok(stat.isDirectory(), 'target not a directory'); + }); + }); +}); + +test('sync root perm', function (t) { + t.plan(3); + + var file = '/tmp'; + mkdirp.sync(file, _0755); + exists(file, function (ex) { + t.ok(ex, 'file created'); + fs.stat(file, function (err, stat) { + t.ifError(err); + t.ok(stat.isDirectory(), 'target not a directory'); + }) + }); +}); diff --git a/express-server/node_modules/mkdirp/test/race.js b/express-server/node_modules/mkdirp/test/race.js new file mode 100644 index 00000000..b0b9e183 --- /dev/null +++ b/express-server/node_modules/mkdirp/test/race.js @@ -0,0 +1,37 @@ +var mkdirp = require('../').mkdirp; +var path = require('path'); +var fs = require('fs'); +var exists = fs.exists || path.exists; +var test = require('tap').test; +var _0777 = parseInt('0777', 8); +var _0755 = parseInt('0755', 8); + +test('race', function (t) { + t.plan(10); + var ps = [ '', 'tmp' ]; + + for (var i = 0; i < 25; i++) { + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + ps.push(dir); + } + var file = ps.join('/'); + + var res = 2; + mk(file); + + mk(file); + + function mk (file, cb) { + mkdirp(file, _0755, function (err) { + t.ifError(err); + exists(file, function (ex) { + t.ok(ex, 'file created'); + fs.stat(file, function (err, stat) { + t.ifError(err); + t.equal(stat.mode & _0777, _0755); + t.ok(stat.isDirectory(), 'target not a directory'); + }); + }) + }); + } +}); diff --git a/express-server/node_modules/mkdirp/test/rel.js b/express-server/node_modules/mkdirp/test/rel.js new file mode 100644 index 00000000..4ddb3427 --- /dev/null +++ b/express-server/node_modules/mkdirp/test/rel.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var exists = fs.exists || path.exists; +var test = require('tap').test; +var _0777 = parseInt('0777', 8); +var _0755 = parseInt('0755', 8); + +test('rel', function (t) { + t.plan(5); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var cwd = process.cwd(); + process.chdir('/tmp'); + + var file = [x,y,z].join('/'); + + mkdirp(file, _0755, function (err) { + t.ifError(err); + exists(file, function (ex) { + t.ok(ex, 'file created'); + fs.stat(file, function (err, stat) { + t.ifError(err); + process.chdir(cwd); + t.equal(stat.mode & _0777, _0755); + t.ok(stat.isDirectory(), 'target not a directory'); + }) + }) + }); +}); diff --git a/express-server/node_modules/mkdirp/test/return.js b/express-server/node_modules/mkdirp/test/return.js new file mode 100644 index 00000000..bce68e56 --- /dev/null +++ b/express-server/node_modules/mkdirp/test/return.js @@ -0,0 +1,25 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('return value', function (t) { + t.plan(4); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + // should return the first dir created. + // By this point, it would be profoundly surprising if /tmp didn't + // already exist, since every other test makes things in there. + mkdirp(file, function (err, made) { + t.ifError(err); + t.equal(made, '/tmp/' + x); + mkdirp(file, function (err, made) { + t.ifError(err); + t.equal(made, null); + }); + }); +}); diff --git a/express-server/node_modules/mkdirp/test/return_sync.js b/express-server/node_modules/mkdirp/test/return_sync.js new file mode 100644 index 00000000..7c222d35 --- /dev/null +++ b/express-server/node_modules/mkdirp/test/return_sync.js @@ -0,0 +1,24 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; + +test('return value', function (t) { + t.plan(2); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + // should return the first dir created. + // By this point, it would be profoundly surprising if /tmp didn't + // already exist, since every other test makes things in there. + // Note that this will throw on failure, which will fail the test. + var made = mkdirp.sync(file); + t.equal(made, '/tmp/' + x); + + // making the same file again should have no effect. + made = mkdirp.sync(file); + t.equal(made, null); +}); diff --git a/express-server/node_modules/mkdirp/test/root.js b/express-server/node_modules/mkdirp/test/root.js new file mode 100644 index 00000000..9e7d079d --- /dev/null +++ b/express-server/node_modules/mkdirp/test/root.js @@ -0,0 +1,19 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var test = require('tap').test; +var _0755 = parseInt('0755', 8); + +test('root', function (t) { + // '/' on unix, 'c:/' on windows. + var file = path.resolve('/'); + + mkdirp(file, _0755, function (err) { + if (err) throw err + fs.stat(file, function (er, stat) { + if (er) throw er + t.ok(stat.isDirectory(), 'target is a directory'); + t.end(); + }) + }); +}); diff --git a/express-server/node_modules/mkdirp/test/sync.js b/express-server/node_modules/mkdirp/test/sync.js new file mode 100644 index 00000000..8c8dc938 --- /dev/null +++ b/express-server/node_modules/mkdirp/test/sync.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var exists = fs.exists || path.exists; +var test = require('tap').test; +var _0777 = parseInt('0777', 8); +var _0755 = parseInt('0755', 8); + +test('sync', function (t) { + t.plan(4); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + try { + mkdirp.sync(file, _0755); + } catch (err) { + t.fail(err); + return t.end(); + } + + exists(file, function (ex) { + t.ok(ex, 'file created'); + fs.stat(file, function (err, stat) { + t.ifError(err); + t.equal(stat.mode & _0777, _0755); + t.ok(stat.isDirectory(), 'target not a directory'); + }); + }); +}); diff --git a/express-server/node_modules/mkdirp/test/umask.js b/express-server/node_modules/mkdirp/test/umask.js new file mode 100644 index 00000000..2033c63a --- /dev/null +++ b/express-server/node_modules/mkdirp/test/umask.js @@ -0,0 +1,28 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var exists = fs.exists || path.exists; +var test = require('tap').test; +var _0777 = parseInt('0777', 8); +var _0755 = parseInt('0755', 8); + +test('implicit mode from umask', function (t) { + t.plan(5); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + mkdirp(file, function (err) { + t.ifError(err); + exists(file, function (ex) { + t.ok(ex, 'file created'); + fs.stat(file, function (err, stat) { + t.ifError(err); + t.equal(stat.mode & _0777, _0777 & (~process.umask())); + t.ok(stat.isDirectory(), 'target not a directory'); + }); + }) + }); +}); diff --git a/express-server/node_modules/mkdirp/test/umask_sync.js b/express-server/node_modules/mkdirp/test/umask_sync.js new file mode 100644 index 00000000..11a76147 --- /dev/null +++ b/express-server/node_modules/mkdirp/test/umask_sync.js @@ -0,0 +1,32 @@ +var mkdirp = require('../'); +var path = require('path'); +var fs = require('fs'); +var exists = fs.exists || path.exists; +var test = require('tap').test; +var _0777 = parseInt('0777', 8); +var _0755 = parseInt('0755', 8); + +test('umask sync modes', function (t) { + t.plan(4); + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16); + + var file = '/tmp/' + [x,y,z].join('/'); + + try { + mkdirp.sync(file); + } catch (err) { + t.fail(err); + return t.end(); + } + + exists(file, function (ex) { + t.ok(ex, 'file created'); + fs.stat(file, function (err, stat) { + t.ifError(err); + t.equal(stat.mode & _0777, (_0777 & (~process.umask()))); + t.ok(stat.isDirectory(), 'target not a directory'); + }); + }); +}); diff --git a/express-server/node_modules/nan/CHANGELOG.md b/express-server/node_modules/nan/CHANGELOG.md new file mode 100644 index 00000000..623918dd --- /dev/null +++ b/express-server/node_modules/nan/CHANGELOG.md @@ -0,0 +1,509 @@ +# NAN ChangeLog + +**Version 2.12.0: current Node 11.4.0, Node 0.12: 0.12.18, Node 0.10: 0.10.48, iojs: 3.3.1** + +### 2.12.0 Dec 16 2018 + +- Bugfix: Add scope.Escape() to Call() (#817) 2e5ed4fc3a8ac80a6ef1f2a55099ab3ac8800dc6 +- Bugfix: Fix Node.js v10.12.0 deprecation warnings. 509859cc23b1770376b56550a027840a2ce0f73d +- Feature: Allow SetWeak() for non-object persistent handles. (#824) e6ef6a48e7e671fe3e4b7dddaa8912a3f8262ecd + +### 2.11.1 Sep 29 2018 + +- Fix: adapt to V8 7.0 24a22c3b25eeeec2016c6ec239bdd6169e985447 + +### 2.11.0 Aug 25 2018 + + - Removal: remove `FunctionCallbackInfo::Callee` for nodejs `>= 10` 1a56c0a6efd4fac944cb46c30912a8e023bda7d4 + - Bugfix: Fix `AsyncProgressWorkerBase::WorkProgress` sends invalid data b0c764d1dab11e9f8b37ffb81e2560a4498aad5e + - Feature: Introduce `GetCurrentEventLoop` b4911b0bb1f6d47d860e10ec014d941c51efac5e + - Feature: Add `NAN_MODULE_WORKER_ENABLED` macro as a replacement for `NAN_MODULE` b058fb047d18a58250e66ae831444441c1f2ac7a + +### 2.10.0 Mar 16 2018 + + - Deprecation: Deprecate `MakeCallback` 5e92b19a59e194241d6a658bd6ff7bfbda372950 + - Feature: add `Nan::Call` overload 4482e1242fe124d166fc1a5b2be3c1cc849fe452 + - Feature: add more `Nan::Call` overloads 8584e63e6d04c7d2eb8c4a664e4ef57d70bf672b + - Feature: Fix deprecation warnings for Node 10 1caf258243b0602ed56922bde74f1c91b0cbcb6a + +### 2.9.2 Feb 22 2018 + + - Bugfix: Bandaid for async hooks 212bd2f849be14ef1b02fc85010b053daa24252b + +### 2.9.1 Feb 22 2018 + + - Bugfix: Avoid deprecation warnings in deprecated `Nan::Callback::operator()` 372b14d91289df4604b0f81780709708c45a9aa4 + - Bugfix: Avoid deprecation warnings in `Nan::JSON` 3bc294bce0b7d0a3ee4559926303e5ed4866fda2 + +### 2.9.0 Feb 22 2018 + + - Deprecation: Deprecate legacy `Callback::Call` 6dd5fa690af61ca3523004b433304c581b3ea309 + - Feature: introduce `AsyncResource` class 90c0a179c0d8cb5fd26f1a7d2b1d6231eb402d48o + - Feature: Add context aware `Nan::Callback::Call` functions 7169e09fb088418b6e388222e88b4c13f07ebaee + - Feature: Make `AsyncWorker` context aware 066ba21a6fb9e2b5230c9ed3a6fc51f1211736a4 + - Feature: add `Callback` overload to `Nan::Call` 5328daf66e202658c1dc0d916c3aaba99b3cc606 + - Bugfix: fix warning: suggest parentheses around `&&` within `||` b2bb63d68b8ae623a526b542764e1ac82319cb2c + - Bugfix: Fix compilation on io.js 3 d06114dba0a522fb436f0c5f47b994210968cd7b + +### 2.8.0 Nov 15 2017 + + - Deprecation: Deprecate `Nan::ForceSet` in favor of `Nan::DefineOwnProperty()` 95cbb976d6fbbba88ba0f86dd188223a8591b4e7 + - Feature: Add `Nan::AsyncProgressQueueWorker` a976636ecc2ef617d1b061ce4a6edf39923691cb + - Feature: Add `Nan::DefineOwnProperty()` 95cbb976d6fbbba88ba0f86dd188223a8591b4e7 + - Bugfix: Fix compiling on io.js 1 & 2 82705a64503ce60c62e98df5bd02972bba090900 + - Bugfix: Use DefineOwnProperty instead of ForceSet 95cbb976d6fbbba88ba0f86dd188223a8591b4e7 + +### 2.7.0 Aug 30 2017 + + - Feature: Add `Nan::To()` overload. b93280670c9f6da42ed4cf6cbf085ffdd87bd65b + - Bugfix: Fix ternary in `Nan::MaybeLocal::FromMaybe()`. 79a26f7d362e756a9524e672a82c3d603b542867 + +### 2.6.2 Apr 12 2017 + + - Bugfix: Fix v8::JSON::Parse() deprecation warning. 87f6a3c65815fa062296a994cc863e2fa124867d + +### 2.6.1 Apr 6 2017 + + - Bugfix: nan_json.h: fix build breakage in Node 6 ac8d47dc3c10bfbf3f15a6b951633120c0ee6d51 + +### 2.6.0 Apr 6 2017 + + - Feature: nan: add support for JSON::Parse & Stringify b533226c629cce70e1932a873bb6f849044a56c5 + +### 2.5.1 Jan 23 2017 + + - Bugfix: Fix disappearing handle for private value 6a80995694f162ef63dbc9948fbefd45d4485aa0 + - Bugfix: Add missing scopes a93b8bae6bc7d32a170db6e89228b7f60ee57112 + - Bugfix: Use string::data instead of string::front in NewOneByteString d5f920371e67e1f3b268295daee6e83af86b6e50 + +### 2.5.0 Dec 21 2016 + + - Feature: Support Private accessors a86255cb357e8ad8ccbf1f6a4a901c921e39a178 + - Bugfix: Abort in delete operators that shouldn't be called 0fe38215ff8581703967dfd26c12793feb960018 + +### 2.4.0 Jul 10 2016 + + - Feature: Rewrite Callback to add Callback::Reset c4cf44d61f8275cd5f7b0c911d7a806d4004f649 + - Feature: AsyncProgressWorker: add template types for .send 1242c9a11a7ed481c8f08ec06316385cacc513d0 + - Bugfix: Add constness to old Persistent comparison operators bd43cb9982c7639605d60fd073efe8cae165d9b2 + +### 2.3.5 May 31 2016 + + - Bugfix: Replace NAN_INLINE with 'inline' keyword. 71819d8725f822990f439479c9aba3b240804909 + +### 2.3.4 May 31 2016 + + - Bugfix: Remove V8 deprecation warnings 0592fb0a47f3a1c7763087ebea8e1138829f24f9 + - Bugfix: Fix new versions not to use WeakCallbackInfo::IsFirstPass 615c19d9e03d4be2049c10db0151edbc3b229246 + - Bugfix: Make ObjectWrap::handle() const d19af99595587fe7a26bd850af6595c2a7145afc + - Bugfix: Fix compilation errors related to 0592fb0a47f3a1c7763087ebea8e1138829f24f9 e9191c525b94f652718325e28610a1adcf90fed8 + +### 2.3.3 May 4 2016 + + - Bugfix: Refactor SetMethod() to deal with v8::Templates (#566) b9083cf6d5de6ebe6bcb49c7502fbb7c0d9ddda8 + +### 2.3.2 Apr 27 2016 + + - Bugfix: Fix compilation on outdated versions due to Handle removal f8b7c875d04d425a41dfd4f3f8345bc3a11e6c52 + +### 2.3.1 Apr 27 2016 + + - Bugfix: Don't use deprecated v8::Template::Set() in SetMethod a90951e9ea70fa1b3836af4b925322919159100e + +### 2.3.0 Apr 27 2016 + + - Feature: added Signal() for invoking async callbacks without sending data from AsyncProgressWorker d8adba45f20e077d00561b20199133620c990b38 + - Bugfix: Don't use deprecated v8::Template::Set() 00dacf0a4b86027415867fa7f1059acc499dcece + +### 2.2.1 Mar 29 2016 + + - Bugfix: Use NewFromUnsigned in ReturnValue::Set(uint32_t i) for pre_12 3a18f9bdce29826e0e4c217854bc476918241a58 + - Performance: Remove unneeeded nullptr checks b715ef44887931c94f0d1605b3b1a4156eebece9 + +### 2.2.0 Jan 9 2016 + + - Feature: Add Function::Call wrapper 4c157474dacf284d125c324177b45aa5dabc08c6 + - Feature: Rename GC*logueCallback to GCCallback for > 4.0 3603435109f981606d300eb88004ca101283acec + - Bugfix: Fix Global::Pass for old versions 367e82a60fbaa52716232cc89db1cc3f685d77d9 + - Bugfix: Remove weird MaybeLocal wrapping of what already is a MaybeLocal 23b4590db10c2ba66aee2338aebe9751c4cb190b + +### 2.1.0 Oct 8 2015 + + - Deprecation: Deprecate NanErrnoException in favor of ErrnoException 0af1ca4cf8b3f0f65ed31bc63a663ab3319da55c + - Feature: added helper class for accessing contents of typedarrays 17b51294c801e534479d5463697a73462d0ca555 + - Feature: [Maybe types] Add MakeMaybe(...) 48d7b53d9702b0c7a060e69ea10fea8fb48d814d + - Feature: new: allow utf16 string with length 66ac6e65c8ab9394ef588adfc59131b3b9d8347b + - Feature: Introduce SetCallHandler and SetCallAsFunctionHandler 7764a9a115d60ba10dc24d86feb0fbc9b4f75537 + - Bugfix: Enable creating Locals from Globals under Node 0.10. 9bf9b8b190821af889790fdc18ace57257e4f9ff + - Bugfix: Fix issue #462 where PropertyCallbackInfo data is not stored safely. 55f50adedd543098526c7b9f4fffd607d3f9861f + +### 2.0.9 Sep 8 2015 + + - Bugfix: EscapableHandleScope in Nan::NewBuffer for Node 0.8 and 0.10 b1654d7 + +### 2.0.8 Aug 28 2015 + + - Work around duplicate linking bug in clang 11902da + +### 2.0.7 Aug 26 2015 + + - Build: Repackage + +### 2.0.6 Aug 26 2015 + + - Bugfix: Properly handle null callback in FunctionTemplate factory 6e99cb1 + - Bugfix: Remove unused static std::map instances 525bddc + - Bugfix: Make better use of maybe versions of APIs bfba85b + - Bugfix: Fix shadowing issues with handle in ObjectWrap 0a9072d + +### 2.0.5 Aug 10 2015 + + - Bugfix: Reimplement weak callback in ObjectWrap 98d38c1 + - Bugfix: Make sure callback classes are not assignable, copyable or movable 81f9b1d + +### 2.0.4 Aug 6 2015 + + - Build: Repackage + +### 2.0.3 Aug 6 2015 + + - Bugfix: Don't use clang++ / g++ syntax extension. 231450e + +### 2.0.2 Aug 6 2015 + + - Build: Repackage + +### 2.0.1 Aug 6 2015 + + - Bugfix: Add workaround for missing REPLACE_INVALID_UTF8 60d6687 + - Bugfix: Reimplement ObjectWrap from scratch to prevent memory leaks 6484601 + - Bugfix: Fix Persistent leak in FunctionCallbackInfo and PropertyCallbackInfo 641ef5f + - Bugfix: Add missing overload for Nan::NewInstance that takes argc/argv 29450ed + +### 2.0.0 Jul 31 2015 + + - Change: Renamed identifiers with leading underscores b5932b4 + - Change: Replaced NanObjectWrapHandle with class NanObjectWrap 464f1e1 + - Change: Replace NanScope and NanEscpableScope macros with classes 47751c4 + - Change: Rename NanNewBufferHandle to NanNewBuffer 6745f99 + - Change: Rename NanBufferUse to NanNewBuffer 3e8b0a5 + - Change: Rename NanNewBuffer to NanCopyBuffer d6af78d + - Change: Remove Nan prefix from all names 72d1f67 + - Change: Update Buffer API for new upstream changes d5d3291 + - Change: Rename Scope and EscapableScope to HandleScope and EscapableHandleScope 21a7a6a + - Change: Get rid of Handles e6c0daf + - Feature: Support io.js 3 with V8 4.4 + - Feature: Introduce NanPersistent 7fed696 + - Feature: Introduce NanGlobal 4408da1 + - Feature: Added NanTryCatch 10f1ca4 + - Feature: Update for V8 v4.3 4b6404a + - Feature: Introduce NanNewOneByteString c543d32 + - Feature: Introduce namespace Nan 67ed1b1 + - Removal: Remove NanLocker and NanUnlocker dd6e401 + - Removal: Remove string converters, except NanUtf8String, which now follows the node implementation b5d00a9 + - Removal: Remove NanReturn* macros d90a25c + - Removal: Remove HasInstance e8f84fe + + +### 1.9.0 Jul 31 2015 + + - Feature: Added `NanFatalException` 81d4a2c + - Feature: Added more error types 4265f06 + - Feature: Added dereference and function call operators to NanCallback c4b2ed0 + - Feature: Added indexed GetFromPersistent and SaveToPersistent edd510c + - Feature: Added more overloads of SaveToPersistent and GetFromPersistent 8b1cef6 + - Feature: Added NanErrnoException dd87d9e + - Correctness: Prevent assign, copy, and move for classes that do not support it 1f55c59, 4b808cb, c96d9b2, fba4a29, 3357130 + - Deprecation: Deprecate `NanGetPointerSafe` and `NanSetPointerSafe` 81d4a2c + - Deprecation: Deprecate `NanBooleanOptionValue` and `NanUInt32OptionValue` 0ad254b + +### 1.8.4 Apr 26 2015 + + - Build: Repackage + +### 1.8.3 Apr 26 2015 + + - Bugfix: Include missing header 1af8648 + +### 1.8.2 Apr 23 2015 + + - Build: Repackage + +### 1.8.1 Apr 23 2015 + + - Bugfix: NanObjectWrapHandle should take a pointer 155f1d3 + +### 1.8.0 Apr 23 2015 + + - Feature: Allow primitives with NanReturnValue 2e4475e + - Feature: Added comparison operators to NanCallback 55b075e + - Feature: Backport thread local storage 15bb7fa + - Removal: Remove support for signatures with arguments 8a2069d + - Correcteness: Replaced NanObjectWrapHandle macro with function 0bc6d59 + +### 1.7.0 Feb 28 2015 + + - Feature: Made NanCallback::Call accept optional target 8d54da7 + - Feature: Support atom-shell 0.21 0b7f1bb + +### 1.6.2 Feb 6 2015 + + - Bugfix: NanEncode: fix argument type for node::Encode on io.js 2be8639 + +### 1.6.1 Jan 23 2015 + + - Build: version bump + +### 1.5.3 Jan 23 2015 + + - Build: repackage + +### 1.6.0 Jan 23 2015 + + - Deprecated `NanNewContextHandle` in favor of `NanNew` 49259af + - Support utility functions moved in newer v8 versions (Node 0.11.15, io.js 1.0) a0aa179 + - Added `NanEncode`, `NanDecodeBytes` and `NanDecodeWrite` 75e6fb9 + +### 1.5.2 Jan 23 2015 + + - Bugfix: Fix non-inline definition build error with clang++ 21d96a1, 60fadd4 + - Bugfix: Readded missing String constructors 18d828f + - Bugfix: Add overload handling NanNew(..) 5ef813b + - Bugfix: Fix uv_work_cb versioning 997e4ae + - Bugfix: Add function factory and test 4eca89c + - Bugfix: Add object template factory and test cdcb951 + - Correctness: Lifted an io.js related typedef c9490be + - Correctness: Make explicit downcasts of String lengths 00074e6 + - Windows: Limit the scope of disabled warning C4530 83d7deb + +### 1.5.1 Jan 15 2015 + + - Build: version bump + +### 1.4.3 Jan 15 2015 + + - Build: version bump + +### 1.4.2 Jan 15 2015 + + - Feature: Support io.js 0dbc5e8 + +### 1.5.0 Jan 14 2015 + + - Feature: Support io.js b003843 + - Correctness: Improved NanNew internals 9cd4f6a + - Feature: Implement progress to NanAsyncWorker 8d6a160 + +### 1.4.1 Nov 8 2014 + + - Bugfix: Handle DEBUG definition correctly + - Bugfix: Accept int as Boolean + +### 1.4.0 Nov 1 2014 + + - Feature: Added NAN_GC_CALLBACK 6a5c245 + - Performance: Removed unnecessary local handle creation 18a7243, 41fe2f8 + - Correctness: Added constness to references in NanHasInstance 02c61cd + - Warnings: Fixed spurious warnings from -Wundef and -Wshadow, 541b122, 99d8cb6 + - Windoze: Shut Visual Studio up when compiling 8d558c1 + - License: Switch to plain MIT from custom hacked MIT license 11de983 + - Build: Added test target to Makefile e232e46 + - Performance: Removed superfluous scope in NanAsyncWorker f4b7821 + - Sugar/Feature: Added NanReturnThis() and NanReturnHolder() shorthands 237a5ff, d697208 + - Feature: Added suitable overload of NanNew for v8::Integer::NewFromUnsigned b27b450 + +### 1.3.0 Aug 2 2014 + + - Added NanNew(std::string) + - Added NanNew(std::string&) + - Added NanAsciiString helper class + - Added NanUtf8String helper class + - Added NanUcs2String helper class + - Deprecated NanRawString() + - Deprecated NanCString() + - Added NanGetIsolateData(v8::Isolate *isolate) + - Added NanMakeCallback(v8::Handle target, v8::Handle func, int argc, v8::Handle* argv) + - Added NanMakeCallback(v8::Handle target, v8::Handle symbol, int argc, v8::Handle* argv) + - Added NanMakeCallback(v8::Handle target, const char* method, int argc, v8::Handle* argv) + - Added NanSetTemplate(v8::Handle templ, v8::Handle name , v8::Handle value, v8::PropertyAttribute attributes) + - Added NanSetPrototypeTemplate(v8::Local templ, v8::Handle name, v8::Handle value, v8::PropertyAttribute attributes) + - Added NanSetInstanceTemplate(v8::Local templ, const char *name, v8::Handle value) + - Added NanSetInstanceTemplate(v8::Local templ, v8::Handle name, v8::Handle value, v8::PropertyAttribute attributes) + +### 1.2.0 Jun 5 2014 + + - Add NanSetPrototypeTemplate + - Changed NAN_WEAK_CALLBACK internals, switched _NanWeakCallbackData to class, + introduced _NanWeakCallbackDispatcher + - Removed -Wno-unused-local-typedefs from test builds + - Made test builds Windows compatible ('Sleep()') + +### 1.1.2 May 28 2014 + + - Release to fix more stuff-ups in 1.1.1 + +### 1.1.1 May 28 2014 + + - Release to fix version mismatch in nan.h and lack of changelog entry for 1.1.0 + +### 1.1.0 May 25 2014 + + - Remove nan_isolate, use v8::Isolate::GetCurrent() internally instead + - Additional explicit overloads for NanNew(): (char*,int), (uint8_t*[,int]), + (uint16_t*[,int), double, int, unsigned int, bool, v8::String::ExternalStringResource*, + v8::String::ExternalAsciiStringResource* + - Deprecate NanSymbol() + - Added SetErrorMessage() and ErrorMessage() to NanAsyncWorker + +### 1.0.0 May 4 2014 + + - Heavy API changes for V8 3.25 / Node 0.11.13 + - Use cpplint.py + - Removed NanInitPersistent + - Removed NanPersistentToLocal + - Removed NanFromV8String + - Removed NanMakeWeak + - Removed NanNewLocal + - Removed NAN_WEAK_CALLBACK_OBJECT + - Removed NAN_WEAK_CALLBACK_DATA + - Introduce NanNew, replaces NanNewLocal, NanPersistentToLocal, adds many overloaded typed versions + - Introduce NanUndefined, NanNull, NanTrue and NanFalse + - Introduce NanEscapableScope and NanEscapeScope + - Introduce NanMakeWeakPersistent (requires a special callback to work on both old and new node) + - Introduce NanMakeCallback for node::MakeCallback + - Introduce NanSetTemplate + - Introduce NanGetCurrentContext + - Introduce NanCompileScript and NanRunScript + - Introduce NanAdjustExternalMemory + - Introduce NanAddGCEpilogueCallback, NanAddGCPrologueCallback, NanRemoveGCEpilogueCallback, NanRemoveGCPrologueCallback + - Introduce NanGetHeapStatistics + - Rename NanAsyncWorker#SavePersistent() to SaveToPersistent() + +### 0.8.0 Jan 9 2014 + + - NanDispose -> NanDisposePersistent, deprecate NanDispose + - Extract _NAN_*_RETURN_TYPE, pull up NAN_*() + +### 0.7.1 Jan 9 2014 + + - Fixes to work against debug builds of Node + - Safer NanPersistentToLocal (avoid reinterpret_cast) + - Speed up common NanRawString case by only extracting flattened string when necessary + +### 0.7.0 Dec 17 2013 + + - New no-arg form of NanCallback() constructor. + - NanCallback#Call takes Handle rather than Local + - Removed deprecated NanCallback#Run method, use NanCallback#Call instead + - Split off _NAN_*_ARGS_TYPE from _NAN_*_ARGS + - Restore (unofficial) Node 0.6 compatibility at NanCallback#Call() + - Introduce NanRawString() for char* (or appropriate void*) from v8::String + (replacement for NanFromV8String) + - Introduce NanCString() for null-terminated char* from v8::String + +### 0.6.0 Nov 21 2013 + + - Introduce NanNewLocal(v8::Handle value) for use in place of + v8::Local::New(...) since v8 started requiring isolate in Node 0.11.9 + +### 0.5.2 Nov 16 2013 + + - Convert SavePersistent and GetFromPersistent in NanAsyncWorker from protected and public + +### 0.5.1 Nov 12 2013 + + - Use node::MakeCallback() instead of direct v8::Function::Call() + +### 0.5.0 Nov 11 2013 + + - Added @TooTallNate as collaborator + - New, much simpler, "include_dirs" for binding.gyp + - Added full range of NAN_INDEX_* macros to match NAN_PROPERTY_* macros + +### 0.4.4 Nov 2 2013 + + - Isolate argument from v8::Persistent::MakeWeak removed for 0.11.8+ + +### 0.4.3 Nov 2 2013 + + - Include node_object_wrap.h, removed from node.h for Node 0.11.8. + +### 0.4.2 Nov 2 2013 + + - Handle deprecation of v8::Persistent::Dispose(v8::Isolate* isolate)) for + Node 0.11.8 release. + +### 0.4.1 Sep 16 2013 + + - Added explicit `#include ` as it was removed from node.h for v0.11.8 + +### 0.4.0 Sep 2 2013 + + - Added NAN_INLINE and NAN_DEPRECATED and made use of them + - Added NanError, NanTypeError and NanRangeError + - Cleaned up code + +### 0.3.2 Aug 30 2013 + + - Fix missing scope declaration in GetFromPersistent() and SaveToPersistent + in NanAsyncWorker + +### 0.3.1 Aug 20 2013 + + - fix "not all control paths return a value" compile warning on some platforms + +### 0.3.0 Aug 19 2013 + + - Made NAN work with NPM + - Lots of fixes to NanFromV8String, pulling in features from new Node core + - Changed node::encoding to Nan::Encoding in NanFromV8String to unify the API + - Added optional error number argument for NanThrowError() + - Added NanInitPersistent() + - Added NanReturnNull() and NanReturnEmptyString() + - Added NanLocker and NanUnlocker + - Added missing scopes + - Made sure to clear disposed Persistent handles + - Changed NanAsyncWorker to allocate error messages on the heap + - Changed NanThrowError(Local) to NanThrowError(Handle) + - Fixed leak in NanAsyncWorker when errmsg is used + +### 0.2.2 Aug 5 2013 + + - Fixed usage of undefined variable with node::BASE64 in NanFromV8String() + +### 0.2.1 Aug 5 2013 + + - Fixed 0.8 breakage, node::BUFFER encoding type not available in 0.8 for + NanFromV8String() + +### 0.2.0 Aug 5 2013 + + - Added NAN_PROPERTY_GETTER, NAN_PROPERTY_SETTER, NAN_PROPERTY_ENUMERATOR, + NAN_PROPERTY_DELETER, NAN_PROPERTY_QUERY + - Extracted _NAN_METHOD_ARGS, _NAN_GETTER_ARGS, _NAN_SETTER_ARGS, + _NAN_PROPERTY_GETTER_ARGS, _NAN_PROPERTY_SETTER_ARGS, + _NAN_PROPERTY_ENUMERATOR_ARGS, _NAN_PROPERTY_DELETER_ARGS, + _NAN_PROPERTY_QUERY_ARGS + - Added NanGetInternalFieldPointer, NanSetInternalFieldPointer + - Added NAN_WEAK_CALLBACK, NAN_WEAK_CALLBACK_OBJECT, + NAN_WEAK_CALLBACK_DATA, NanMakeWeak + - Renamed THROW_ERROR to _NAN_THROW_ERROR + - Added NanNewBufferHandle(char*, size_t, node::smalloc::FreeCallback, void*) + - Added NanBufferUse(char*, uint32_t) + - Added NanNewContextHandle(v8::ExtensionConfiguration*, + v8::Handle, v8::Handle) + - Fixed broken NanCallback#GetFunction() + - Added optional encoding and size arguments to NanFromV8String() + - Added NanGetPointerSafe() and NanSetPointerSafe() + - Added initial test suite (to be expanded) + - Allow NanUInt32OptionValue to convert any Number object + +### 0.1.0 Jul 21 2013 + + - Added `NAN_GETTER`, `NAN_SETTER` + - Added `NanThrowError` with single Local argument + - Added `NanNewBufferHandle` with single uint32_t argument + - Added `NanHasInstance(Persistent&, Handle)` + - Added `Local NanCallback#GetFunction()` + - Added `NanCallback#Call(int, Local[])` + - Deprecated `NanCallback#Run(int, Local[])` in favour of Call diff --git a/express-server/node_modules/nan/LICENSE.md b/express-server/node_modules/nan/LICENSE.md new file mode 100644 index 00000000..dddd13d5 --- /dev/null +++ b/express-server/node_modules/nan/LICENSE.md @@ -0,0 +1,13 @@ +The MIT License (MIT) +===================== + +Copyright (c) 2018 NAN contributors +----------------------------------- + +*NAN contributors listed at * + +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/express-server/node_modules/nan/README.md b/express-server/node_modules/nan/README.md new file mode 100644 index 00000000..17c9874e --- /dev/null +++ b/express-server/node_modules/nan/README.md @@ -0,0 +1,456 @@ +Native Abstractions for Node.js +=============================== + +**A header file filled with macro and utility goodness for making add-on development for Node.js easier across versions 0.8, 0.10, 0.12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 and 11.** + +***Current version: 2.12.0*** + +*(See [CHANGELOG.md](https://github.com/nodejs/nan/blob/master/CHANGELOG.md) for complete ChangeLog)* + +[![NPM](https://nodei.co/npm/nan.png?downloads=true&downloadRank=true)](https://nodei.co/npm/nan/) [![NPM](https://nodei.co/npm-dl/nan.png?months=6&height=3)](https://nodei.co/npm/nan/) + +[![Build Status](https://api.travis-ci.org/nodejs/nan.svg?branch=master)](https://travis-ci.org/nodejs/nan) +[![Build status](https://ci.appveyor.com/api/projects/status/kh73pbm9dsju7fgh)](https://ci.appveyor.com/project/RodVagg/nan) + +Thanks to the crazy changes in V8 (and some in Node core), keeping native addons compiling happily across versions, particularly 0.10 to 0.12 to 4.0, is a minor nightmare. The goal of this project is to store all logic necessary to develop native Node.js addons without having to inspect `NODE_MODULE_VERSION` and get yourself into a macro-tangle. + +This project also contains some helper utilities that make addon development a bit more pleasant. + + * **[News & Updates](#news)** + * **[Usage](#usage)** + * **[Example](#example)** + * **[API](#api)** + * **[Tests](#tests)** + * **[Knowns issues](#issues)** + * **[Governance & Contributing](#governance)** + + + +## News & Updates + + + +## Usage + +Simply add **NAN** as a dependency in the *package.json* of your Node addon: + +``` bash +$ npm install --save nan +``` + +Pull in the path to **NAN** in your *binding.gyp* so that you can use `#include ` in your *.cpp* files: + +``` python +"include_dirs" : [ + "` when compiling your addon. + + + +## Example + +Just getting started with Nan? Take a look at the **[Node Add-on Examples](https://github.com/nodejs/node-addon-examples)**. + +Refer to a [quick-start **Nan** Boilerplate](https://github.com/fcanas/node-native-boilerplate) for a ready-to-go project that utilizes basic Nan functionality. + +For a simpler example, see the **[async pi estimation example](https://github.com/nodejs/nan/tree/master/examples/async_pi_estimate)** in the examples directory for full code and an explanation of what this Monte Carlo Pi estimation example does. Below are just some parts of the full example that illustrate the use of **NAN**. + +Yet another example is **[nan-example-eol](https://github.com/CodeCharmLtd/nan-example-eol)**. It shows newline detection implemented as a native addon. + +Also take a look at our comprehensive **[C++ test suite](https://github.com/nodejs/nan/tree/master/test/cpp)** which has a plethora of code snippets for your pasting pleasure. + + + +## API + +Additional to the NAN documentation below, please consult: + +* [The V8 Getting Started * Guide](https://github.com/v8/v8/wiki/Getting%20Started%20with%20Embedding) +* [The V8 Embedders * Guide](https://github.com/v8/v8/wiki/Embedder%27s%20Guide) +* [V8 API Documentation](https://v8docs.nodesource.com/) +* [Node Add-on Documentation](https://nodejs.org/api/addons.html) + + + +### JavaScript-accessible methods + +A _template_ is a blueprint for JavaScript functions and objects in a context. You can use a template to wrap C++ functions and data structures within JavaScript objects so that they can be manipulated from JavaScript. See the V8 Embedders Guide section on [Templates](https://github.com/v8/v8/wiki/Embedder%27s-Guide#templates) for further information. + +In order to expose functionality to JavaScript via a template, you must provide it to V8 in a form that it understands. Across the versions of V8 supported by NAN, JavaScript-accessible method signatures vary widely, NAN fully abstracts method declaration and provides you with an interface that is similar to the most recent V8 API but is backward-compatible with older versions that still use the now-deceased `v8::Argument` type. + +* **Method argument types** + - Nan::FunctionCallbackInfo + - Nan::PropertyCallbackInfo + - Nan::ReturnValue +* **Method declarations** + - Method declaration + - Getter declaration + - Setter declaration + - Property getter declaration + - Property setter declaration + - Property enumerator declaration + - Property deleter declaration + - Property query declaration + - Index getter declaration + - Index setter declaration + - Index enumerator declaration + - Index deleter declaration + - Index query declaration +* Method and template helpers + - Nan::SetMethod() + - Nan::SetPrototypeMethod() + - Nan::SetAccessor() + - Nan::SetNamedPropertyHandler() + - Nan::SetIndexedPropertyHandler() + - Nan::SetTemplate() + - Nan::SetPrototypeTemplate() + - Nan::SetInstanceTemplate() + - Nan::SetCallHandler() + - Nan::SetCallAsFunctionHandler() + +### Scopes + +A _local handle_ is a pointer to an object. All V8 objects are accessed using handles, they are necessary because of the way the V8 garbage collector works. + +A handle scope can be thought of as a container for any number of handles. When you've finished with your handles, instead of deleting each one individually you can simply delete their scope. + +The creation of `HandleScope` objects is different across the supported versions of V8. Therefore, NAN provides its own implementations that can be used safely across these. + + - Nan::HandleScope + - Nan::EscapableHandleScope + +Also see the V8 Embedders Guide section on [Handles and Garbage Collection](https://github.com/v8/v8/wiki/Embedder%27s%20Guide#handles-and-garbage-collection). + +### Persistent references + +An object reference that is independent of any `HandleScope` is a _persistent_ reference. Where a `Local` handle only lives as long as the `HandleScope` in which it was allocated, a `Persistent` handle remains valid until it is explicitly disposed. + +Due to the evolution of the V8 API, it is necessary for NAN to provide a wrapper implementation of the `Persistent` classes to supply compatibility across the V8 versions supported. + + - Nan::PersistentBase & v8::PersistentBase + - Nan::NonCopyablePersistentTraits & v8::NonCopyablePersistentTraits + - Nan::CopyablePersistentTraits & v8::CopyablePersistentTraits + - Nan::Persistent + - Nan::Global + - Nan::WeakCallbackInfo + - Nan::WeakCallbackType + +Also see the V8 Embedders Guide section on [Handles and Garbage Collection](https://developers.google.com/v8/embed#handles). + +### New + +NAN provides a `Nan::New()` helper for the creation of new JavaScript objects in a way that's compatible across the supported versions of V8. + + - Nan::New() + - Nan::Undefined() + - Nan::Null() + - Nan::True() + - Nan::False() + - Nan::EmptyString() + + +### Converters + +NAN contains functions that convert `v8::Value`s to other `v8::Value` types and native types. Since type conversion is not guaranteed to succeed, they return `Nan::Maybe` types. These converters can be used in place of `value->ToX()` and `value->XValue()` (where `X` is one of the types, e.g. `Boolean`) in a way that provides a consistent interface across V8 versions. Newer versions of V8 use the new `v8::Maybe` and `v8::MaybeLocal` types for these conversions, older versions don't have this functionality so it is provided by NAN. + + - Nan::To() + +### Maybe Types + +The `Nan::MaybeLocal` and `Nan::Maybe` types are monads that encapsulate `v8::Local` handles that _may be empty_. + +* **Maybe Types** + - Nan::MaybeLocal + - Nan::Maybe + - Nan::Nothing + - Nan::Just +* **Maybe Helpers** + - Nan::Call() + - Nan::ToDetailString() + - Nan::ToArrayIndex() + - Nan::Equals() + - Nan::NewInstance() + - Nan::GetFunction() + - Nan::Set() + - Nan::DefineOwnProperty() + - Nan::ForceSet() + - Nan::Get() + - Nan::GetPropertyAttributes() + - Nan::Has() + - Nan::Delete() + - Nan::GetPropertyNames() + - Nan::GetOwnPropertyNames() + - Nan::SetPrototype() + - Nan::ObjectProtoToString() + - Nan::HasOwnProperty() + - Nan::HasRealNamedProperty() + - Nan::HasRealIndexedProperty() + - Nan::HasRealNamedCallbackProperty() + - Nan::GetRealNamedPropertyInPrototypeChain() + - Nan::GetRealNamedProperty() + - Nan::CallAsFunction() + - Nan::CallAsConstructor() + - Nan::GetSourceLine() + - Nan::GetLineNumber() + - Nan::GetStartColumn() + - Nan::GetEndColumn() + - Nan::CloneElementAt() + - Nan::HasPrivate() + - Nan::GetPrivate() + - Nan::SetPrivate() + - Nan::DeletePrivate() + - Nan::MakeMaybe() + +### Script + +NAN provides a `v8::Script` helpers as the API has changed over the supported versions of V8. + + - Nan::CompileScript() + - Nan::RunScript() + + +### JSON + +The _JSON_ object provides the c++ versions of the methods offered by the `JSON` object in javascript. V8 exposes these methods via the `v8::JSON` object. + + - Nan::JSON.Parse + - Nan::JSON.Stringify + +Refer to the V8 JSON object in the [V8 documentation](https://v8docs.nodesource.com/node-8.11/da/d6f/classv8_1_1_j_s_o_n.html) for more information about these methods and their arguments. + +### Errors + +NAN includes helpers for creating, throwing and catching Errors as much of this functionality varies across the supported versions of V8 and must be abstracted. + +Note that an Error object is simply a specialized form of `v8::Value`. + +Also consult the V8 Embedders Guide section on [Exceptions](https://developers.google.com/v8/embed#exceptions) for more information. + + - Nan::Error() + - Nan::RangeError() + - Nan::ReferenceError() + - Nan::SyntaxError() + - Nan::TypeError() + - Nan::ThrowError() + - Nan::ThrowRangeError() + - Nan::ThrowReferenceError() + - Nan::ThrowSyntaxError() + - Nan::ThrowTypeError() + - Nan::FatalException() + - Nan::ErrnoException() + - Nan::TryCatch + + +### Buffers + +NAN's `node::Buffer` helpers exist as the API has changed across supported Node versions. Use these methods to ensure compatibility. + + - Nan::NewBuffer() + - Nan::CopyBuffer() + - Nan::FreeCallback() + +### Nan::Callback + +`Nan::Callback` makes it easier to use `v8::Function` handles as callbacks. A class that wraps a `v8::Function` handle, protecting it from garbage collection and making it particularly useful for storage and use across asynchronous execution. + + - Nan::Callback + +### Asynchronous work helpers + +`Nan::AsyncWorker`, `Nan::AsyncProgressWorker` and `Nan::AsyncProgressQueueWorker` are helper classes that make working with asynchronous code easier. + + - Nan::AsyncWorker + - Nan::AsyncProgressWorkerBase & Nan::AsyncProgressWorker + - Nan::AsyncProgressQueueWorker + - Nan::AsyncQueueWorker + +### Strings & Bytes + +Miscellaneous string & byte encoding and decoding functionality provided for compatibility across supported versions of V8 and Node. Implemented by NAN to ensure that all encoding types are supported, even for older versions of Node where they are missing. + + - Nan::Encoding + - Nan::Encode() + - Nan::DecodeBytes() + - Nan::DecodeWrite() + + +### Object Wrappers + +The `ObjectWrap` class can be used to make wrapped C++ objects and a factory of wrapped objects. + + - Nan::ObjectWrap + + +### V8 internals + +The hooks to access V8 internals—including GC and statistics—are different across the supported versions of V8, therefore NAN provides its own hooks that call the appropriate V8 methods. + + - NAN_GC_CALLBACK() + - Nan::AddGCEpilogueCallback() + - Nan::RemoveGCEpilogueCallback() + - Nan::AddGCPrologueCallback() + - Nan::RemoveGCPrologueCallback() + - Nan::GetHeapStatistics() + - Nan::SetCounterFunction() + - Nan::SetCreateHistogramFunction() + - Nan::SetAddHistogramSampleFunction() + - Nan::IdleNotification() + - Nan::LowMemoryNotification() + - Nan::ContextDisposedNotification() + - Nan::GetInternalFieldPointer() + - Nan::SetInternalFieldPointer() + - Nan::AdjustExternalMemory() + + +### Miscellaneous V8 Helpers + + - Nan::Utf8String + - Nan::GetCurrentContext() + - Nan::SetIsolateData() + - Nan::GetIsolateData() + - Nan::TypedArrayContents + + +### Miscellaneous Node Helpers + + - Nan::AsyncResource + - Nan::MakeCallback() + - NAN_MODULE_INIT() + - Nan::Export() + + + + + + +### Tests + +To run the NAN tests do: + +``` sh +npm install +npm run-script rebuild-tests +npm test +``` + +Or just: + +``` sh +npm install +make test +``` + + + +## Known issues + +### Compiling against Node.js 0.12 on OSX + +With new enough compilers available on OSX, the versions of V8 headers corresponding to Node.js 0.12 +do not compile anymore. The error looks something like: + +``` +❯ CXX(target) Release/obj.target/accessors/cpp/accessors.o +In file included from ../cpp/accessors.cpp:9: +In file included from ../../nan.h:51: +In file included from /Users/ofrobots/.node-gyp/0.12.18/include/node/node.h:61: +/Users/ofrobots/.node-gyp/0.12.18/include/node/v8.h:5800:54: error: 'CreateHandle' is a protected member of 'v8::HandleScope' + return Handle(reinterpret_cast(HandleScope::CreateHandle( + ~~~~~~~~~~~~~^~~~~~~~~~~~ +``` + +This can be worked around by patching your local versions of v8.h corresponding to Node 0.12 to make +`v8::Handle` a friend of `v8::HandleScope`. Since neither Node.js not V8 support this release line anymore +this patch cannot be released by either project in an official release. + +For this reason, we do not test against Node.js 0.12 on OSX in this project's CI. If you need to support +that configuration, you will need to either get an older compiler, or apply a source patch to the version +of V8 headers as a workaround. + + + +## Governance & Contributing + +NAN is governed by the [Node.js Addon API Working Group](https://github.com/nodejs/CTC/blob/master/WORKING_GROUPS.md#addon-api) + +### Addon API Working Group (WG) + +The NAN project is jointly governed by a Working Group which is responsible for high-level guidance of the project. + +Members of the WG are also known as Collaborators, there is no distinction between the two, unlike other Node.js projects. + +The WG has final authority over this project including: + +* Technical direction +* Project governance and process (including this policy) +* Contribution policy +* GitHub repository hosting +* Maintaining the list of additional Collaborators + +For the current list of WG members, see the project [README.md](./README.md#collaborators). + +Individuals making significant and valuable contributions are made members of the WG and given commit-access to the project. These individuals are identified by the WG and their addition to the WG is discussed via GitHub and requires unanimous consensus amongst those WG members participating in the discussion with a quorum of 50% of WG members required for acceptance of the vote. + +_Note:_ If you make a significant contribution and are not considered for commit-access log an issue or contact a WG member directly. + +For the current list of WG members / Collaborators, see the project [README.md](./README.md#collaborators). + +### Consensus Seeking Process + +The WG follows a [Consensus Seeking](https://en.wikipedia.org/wiki/Consensus-seeking_decision-making) decision making model. + +Modifications of the contents of the NAN repository are made on a collaborative basis. Anybody with a GitHub account may propose a modification via pull request and it will be considered by the WG. All pull requests must be reviewed and accepted by a WG member with sufficient expertise who is able to take full responsibility for the change. In the case of pull requests proposed by an existing WG member, an additional WG member is required for sign-off. Consensus should be sought if additional WG members participate and there is disagreement around a particular modification. + +If a change proposal cannot reach a consensus, a WG member can call for a vote amongst the members of the WG. Simple majority wins. + + + +## Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +* (a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +* (b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +* (c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +* (d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. + + + +### WG Members / Collaborators + + + + + + + + + + +
Rod VaggGitHub/rvaggTwitter/@rvagg
Benjamin ByholmGitHub/kkoopa-
Trevor NorrisGitHub/trevnorrisTwitter/@trevnorris
Nathan RajlichGitHub/TooTallNateTwitter/@TooTallNate
Brett LawsonGitHub/brett19Twitter/@brett19x
Ben NoordhuisGitHub/bnoordhuisTwitter/@bnoordhuis
David SiegelGitHub/agnatTwitter/@agnat
Michael Ira KrufkyGitHub/mkrufkyTwitter/@mkrufky
+ +## Licence & copyright + +Copyright (c) 2018 NAN WG Members / Collaborators (listed above). + +Native Abstractions for Node.js is licensed under an MIT license. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE file for more details. diff --git a/express-server/node_modules/nan/doc/asyncworker.md b/express-server/node_modules/nan/doc/asyncworker.md new file mode 100644 index 00000000..3963ff57 --- /dev/null +++ b/express-server/node_modules/nan/doc/asyncworker.md @@ -0,0 +1,146 @@ +## Asynchronous work helpers + +`Nan::AsyncWorker`, `Nan::AsyncProgressWorker` and `Nan::AsyncProgressQueueWorker` are helper classes that make working with asynchronous code easier. + + - Nan::AsyncWorker + - Nan::AsyncProgressWorkerBase & Nan::AsyncProgressWorker + - Nan::AsyncProgressQueueWorker + - Nan::AsyncQueueWorker + + +### Nan::AsyncWorker + +`Nan::AsyncWorker` is an _abstract_ class that you can subclass to have much of the annoying asynchronous queuing and handling taken care of for you. It can even store arbitrary V8 objects for you and have them persist while the asynchronous work is in progress. + +This class internally handles the details of creating an [`AsyncResource`][AsyncResource], and running the callback in the +correct async context. To be able to identify the async resources created by this class in async-hooks, provide a +`resource_name` to the constructor. It is recommended that the module name be used as a prefix to the `resource_name` to avoid +collisions in the names. For more details see [`AsyncResource`][AsyncResource] documentation. The `resource_name` needs to stay valid for the lifetime of the worker instance. + +Definition: + +```c++ +class AsyncWorker { + public: + explicit AsyncWorker(Callback *callback_, const char* resource_name = "nan:AsyncWorker"); + + virtual ~AsyncWorker(); + + virtual void WorkComplete(); + + void SaveToPersistent(const char *key, const v8::Local &value); + + void SaveToPersistent(const v8::Local &key, + const v8::Local &value); + + void SaveToPersistent(uint32_t index, + const v8::Local &value); + + v8::Local GetFromPersistent(const char *key) const; + + v8::Local GetFromPersistent(const v8::Local &key) const; + + v8::Local GetFromPersistent(uint32_t index) const; + + virtual void Execute() = 0; + + uv_work_t request; + + virtual void Destroy(); + + protected: + Persistent persistentHandle; + + Callback *callback; + + virtual void HandleOKCallback(); + + virtual void HandleErrorCallback(); + + void SetErrorMessage(const char *msg); + + const char* ErrorMessage(); +}; +``` + + +### Nan::AsyncProgressWorkerBase & Nan::AsyncProgressWorker + +`Nan::AsyncProgressWorkerBase` is an _abstract_ class template that extends `Nan::AsyncWorker` and adds additional progress reporting callbacks that can be used during the asynchronous work execution to provide progress data back to JavaScript. + +Previously the definiton of `Nan::AsyncProgressWorker` only allowed sending `const char` data. Now extending `Nan::AsyncProgressWorker` will yield an instance of the implicit `Nan::AsyncProgressWorkerBase` template with type `` for compatibility. + +`Nan::AsyncProgressWorkerBase` & `Nan::AsyncProgressWorker` is intended for best-effort delivery of nonessential progress messages, e.g. a progress bar. The last event sent before the main thread is woken will be delivered. + +Definition: + +```c++ +template +class AsyncProgressWorkerBase : public AsyncWorker { + public: + explicit AsyncProgressWorkerBase(Callback *callback_, const char* resource_name = ...); + + virtual ~AsyncProgressWorkerBase(); + + void WorkProgress(); + + class ExecutionProgress { + public: + void Signal() const; + void Send(const T* data, size_t count) const; + }; + + virtual void Execute(const ExecutionProgress& progress) = 0; + + virtual void HandleProgressCallback(const T *data, size_t count) = 0; + + virtual void Destroy(); +}; + +typedef AsyncProgressWorkerBase AsyncProgressWorker; +``` + + +### Nan::AsyncProgressQueueWorker + +`Nan::AsyncProgressQueueWorker` is an _abstract_ class template that extends `Nan::AsyncWorker` and adds additional progress reporting callbacks that can be used during the asynchronous work execution to provide progress data back to JavaScript. + +`Nan::AsyncProgressQueueWorker` behaves exactly the same as `Nan::AsyncProgressWorker`, except all events are queued and delivered to the main thread. + +Definition: + +```c++ +template +class AsyncProgressQueueWorker : public AsyncWorker { + public: + explicit AsyncProgressQueueWorker(Callback *callback_, const char* resource_name = "nan:AsyncProgressQueueWorker"); + + virtual ~AsyncProgressQueueWorker(); + + void WorkProgress(); + + class ExecutionProgress { + public: + void Send(const T* data, size_t count) const; + }; + + virtual void Execute(const ExecutionProgress& progress) = 0; + + virtual void HandleProgressCallback(const T *data, size_t count) = 0; + + virtual void Destroy(); +}; +``` + + +### Nan::AsyncQueueWorker + +`Nan::AsyncQueueWorker` will run a `Nan::AsyncWorker` asynchronously via libuv. Both the `execute` and `after_work` steps are taken care of for you. Most of the logic for this is embedded in `Nan::AsyncWorker`. + +Definition: + +```c++ +void AsyncQueueWorker(AsyncWorker *); +``` + +[AsyncResource]: node_misc.md#api_nan_asyncresource diff --git a/express-server/node_modules/nan/doc/buffers.md b/express-server/node_modules/nan/doc/buffers.md new file mode 100644 index 00000000..8d8d25cf --- /dev/null +++ b/express-server/node_modules/nan/doc/buffers.md @@ -0,0 +1,54 @@ +## Buffers + +NAN's `node::Buffer` helpers exist as the API has changed across supported Node versions. Use these methods to ensure compatibility. + + - Nan::NewBuffer() + - Nan::CopyBuffer() + - Nan::FreeCallback() + + +### Nan::NewBuffer() + +Allocate a new `node::Buffer` object with the specified size and optional data. Calls `node::Buffer::New()`. + +Note that when creating a `Buffer` using `Nan::NewBuffer()` and an existing `char*`, it is assumed that the ownership of the pointer is being transferred to the new `Buffer` for management. +When a `node::Buffer` instance is garbage collected and a `FreeCallback` has not been specified, `data` will be disposed of via a call to `free()`. +You _must not_ free the memory space manually once you have created a `Buffer` in this way. + +Signature: + +```c++ +Nan::MaybeLocal Nan::NewBuffer(uint32_t size) +Nan::MaybeLocal Nan::NewBuffer(char* data, uint32_t size) +Nan::MaybeLocal Nan::NewBuffer(char *data, + size_t length, + Nan::FreeCallback callback, + void *hint) +``` + + + +### Nan::CopyBuffer() + +Similar to [`Nan::NewBuffer()`](#api_nan_new_buffer) except that an implicit memcpy will occur within Node. Calls `node::Buffer::Copy()`. + +Management of the `char*` is left to the user, you should manually free the memory space if necessary as the new `Buffer` will have its own copy. + +Signature: + +```c++ +Nan::MaybeLocal Nan::CopyBuffer(const char *data, uint32_t size) +``` + + + +### Nan::FreeCallback() + +A free callback that can be provided to [`Nan::NewBuffer()`](#api_nan_new_buffer). +The supplied callback will be invoked when the `Buffer` undergoes garbage collection. + +Signature: + +```c++ +typedef void (*FreeCallback)(char *data, void *hint); +``` diff --git a/express-server/node_modules/nan/doc/callback.md b/express-server/node_modules/nan/doc/callback.md new file mode 100644 index 00000000..f7af0bfd --- /dev/null +++ b/express-server/node_modules/nan/doc/callback.md @@ -0,0 +1,76 @@ +## Nan::Callback + +`Nan::Callback` makes it easier to use `v8::Function` handles as callbacks. A class that wraps a `v8::Function` handle, protecting it from garbage collection and making it particularly useful for storage and use across asynchronous execution. + + - Nan::Callback + + +### Nan::Callback + +```c++ +class Callback { + public: + Callback(); + + explicit Callback(const v8::Local &fn); + + ~Callback(); + + bool operator==(const Callback &other) const; + + bool operator!=(const Callback &other) const; + + v8::Local operator*() const; + + MaybeLocal operator()(AsyncResource* async_resource, + v8::Local target, + int argc = 0, + v8::Local argv[] = 0) const; + + MaybeLocal operator()(AsyncResource* async_resource, + int argc = 0, + v8::Local argv[] = 0) const; + + void SetFunction(const v8::Local &fn); + + v8::Local GetFunction() const; + + bool IsEmpty() const; + + void Reset(const v8::Local &fn); + + void Reset(); + + MaybeLocal Call(v8::Local target, + int argc, + v8::Local argv[], + AsyncResource* async_resource) const; + MaybeLocal Call(int argc, + v8::Local argv[], + AsyncResource* async_resource) const; + + // Deprecated versions. Use the versions that accept an async_resource instead + // as they run the callback in the correct async context as specified by the + // resource. If you want to call a synchronous JS function (i.e. on a + // non-empty JS stack), you can use Nan::Call instead. + v8::Local operator()(v8::Local target, + int argc = 0, + v8::Local argv[] = 0) const; + + v8::Local operator()(int argc = 0, + v8::Local argv[] = 0) const; + v8::Local Call(v8::Local target, + int argc, + v8::Local argv[]) const; + + v8::Local Call(int argc, v8::Local argv[]) const; +}; +``` + +Example usage: + +```c++ +v8::Local function; +Nan::Callback callback(function); +callback.Call(0, 0); +``` diff --git a/express-server/node_modules/nan/doc/converters.md b/express-server/node_modules/nan/doc/converters.md new file mode 100644 index 00000000..d20861b5 --- /dev/null +++ b/express-server/node_modules/nan/doc/converters.md @@ -0,0 +1,41 @@ +## Converters + +NAN contains functions that convert `v8::Value`s to other `v8::Value` types and native types. Since type conversion is not guaranteed to succeed, they return `Nan::Maybe` types. These converters can be used in place of `value->ToX()` and `value->XValue()` (where `X` is one of the types, e.g. `Boolean`) in a way that provides a consistent interface across V8 versions. Newer versions of V8 use the new `v8::Maybe` and `v8::MaybeLocal` types for these conversions, older versions don't have this functionality so it is provided by NAN. + + - Nan::To() + + +### Nan::To() + +Converts a `v8::Local` to a different subtype of `v8::Value` or to a native data type. Returns a `Nan::MaybeLocal<>` or a `Nan::Maybe<>` accordingly. + +See [maybe_types.md](./maybe_types.md) for more information on `Nan::Maybe` types. + +Signatures: + +```c++ +// V8 types +Nan::MaybeLocal Nan::To(v8::Local val); +Nan::MaybeLocal Nan::To(v8::Local val); +Nan::MaybeLocal Nan::To(v8::Local val); +Nan::MaybeLocal Nan::To(v8::Local val); +Nan::MaybeLocal Nan::To(v8::Local val); +Nan::MaybeLocal Nan::To(v8::Local val); +Nan::MaybeLocal Nan::To(v8::Local val); + +// Native types +Nan::Maybe Nan::To(v8::Local val); +Nan::Maybe Nan::To(v8::Local val); +Nan::Maybe Nan::To(v8::Local val); +Nan::Maybe Nan::To(v8::Local val); +Nan::Maybe Nan::To(v8::Local val); +``` + +### Example + +```c++ +v8::Local val; +Nan::MaybeLocal str = Nan::To(val); +Nan::Maybe d = Nan::To(val); +``` + diff --git a/express-server/node_modules/nan/doc/errors.md b/express-server/node_modules/nan/doc/errors.md new file mode 100644 index 00000000..8127a548 --- /dev/null +++ b/express-server/node_modules/nan/doc/errors.md @@ -0,0 +1,226 @@ +## Errors + +NAN includes helpers for creating, throwing and catching Errors as much of this functionality varies across the supported versions of V8 and must be abstracted. + +Note that an Error object is simply a specialized form of `v8::Value`. + +Also consult the V8 Embedders Guide section on [Exceptions](https://developers.google.com/v8/embed#exceptions) for more information. + + - Nan::Error() + - Nan::RangeError() + - Nan::ReferenceError() + - Nan::SyntaxError() + - Nan::TypeError() + - Nan::ThrowError() + - Nan::ThrowRangeError() + - Nan::ThrowReferenceError() + - Nan::ThrowSyntaxError() + - Nan::ThrowTypeError() + - Nan::FatalException() + - Nan::ErrnoException() + - Nan::TryCatch + + + +### Nan::Error() + +Create a new Error object using the [v8::Exception](https://v8docs.nodesource.com/node-8.11/da/d6a/classv8_1_1_exception.html) class in a way that is compatible across the supported versions of V8. + +Note that an Error object is simply a specialized form of `v8::Value`. + +Signature: + +```c++ +v8::Local Nan::Error(const char *msg); +v8::Local Nan::Error(v8::Local msg); +``` + + + +### Nan::RangeError() + +Create a new RangeError object using the [v8::Exception](https://v8docs.nodesource.com/node-8.11/da/d6a/classv8_1_1_exception.html) class in a way that is compatible across the supported versions of V8. + +Note that an RangeError object is simply a specialized form of `v8::Value`. + +Signature: + +```c++ +v8::Local Nan::RangeError(const char *msg); +v8::Local Nan::RangeError(v8::Local msg); +``` + + + +### Nan::ReferenceError() + +Create a new ReferenceError object using the [v8::Exception](https://v8docs.nodesource.com/node-8.11/da/d6a/classv8_1_1_exception.html) class in a way that is compatible across the supported versions of V8. + +Note that an ReferenceError object is simply a specialized form of `v8::Value`. + +Signature: + +```c++ +v8::Local Nan::ReferenceError(const char *msg); +v8::Local Nan::ReferenceError(v8::Local msg); +``` + + + +### Nan::SyntaxError() + +Create a new SyntaxError object using the [v8::Exception](https://v8docs.nodesource.com/node-8.11/da/d6a/classv8_1_1_exception.html) class in a way that is compatible across the supported versions of V8. + +Note that an SyntaxError object is simply a specialized form of `v8::Value`. + +Signature: + +```c++ +v8::Local Nan::SyntaxError(const char *msg); +v8::Local Nan::SyntaxError(v8::Local msg); +``` + + + +### Nan::TypeError() + +Create a new TypeError object using the [v8::Exception](https://v8docs.nodesource.com/node-8.11/da/d6a/classv8_1_1_exception.html) class in a way that is compatible across the supported versions of V8. + +Note that an TypeError object is simply a specialized form of `v8::Value`. + +Signature: + +```c++ +v8::Local Nan::TypeError(const char *msg); +v8::Local Nan::TypeError(v8::Local msg); +``` + + + +### Nan::ThrowError() + +Throw an Error object (a specialized `v8::Value` as above) in the current context. If a `msg` is provided, a new Error object will be created. + +Signature: + +```c++ +void Nan::ThrowError(const char *msg); +void Nan::ThrowError(v8::Local msg); +void Nan::ThrowError(v8::Local error); +``` + + + +### Nan::ThrowRangeError() + +Throw an RangeError object (a specialized `v8::Value` as above) in the current context. If a `msg` is provided, a new RangeError object will be created. + +Signature: + +```c++ +void Nan::ThrowRangeError(const char *msg); +void Nan::ThrowRangeError(v8::Local msg); +void Nan::ThrowRangeError(v8::Local error); +``` + + + +### Nan::ThrowReferenceError() + +Throw an ReferenceError object (a specialized `v8::Value` as above) in the current context. If a `msg` is provided, a new ReferenceError object will be created. + +Signature: + +```c++ +void Nan::ThrowReferenceError(const char *msg); +void Nan::ThrowReferenceError(v8::Local msg); +void Nan::ThrowReferenceError(v8::Local error); +``` + + + +### Nan::ThrowSyntaxError() + +Throw an SyntaxError object (a specialized `v8::Value` as above) in the current context. If a `msg` is provided, a new SyntaxError object will be created. + +Signature: + +```c++ +void Nan::ThrowSyntaxError(const char *msg); +void Nan::ThrowSyntaxError(v8::Local msg); +void Nan::ThrowSyntaxError(v8::Local error); +``` + + + +### Nan::ThrowTypeError() + +Throw an TypeError object (a specialized `v8::Value` as above) in the current context. If a `msg` is provided, a new TypeError object will be created. + +Signature: + +```c++ +void Nan::ThrowTypeError(const char *msg); +void Nan::ThrowTypeError(v8::Local msg); +void Nan::ThrowTypeError(v8::Local error); +``` + + +### Nan::FatalException() + +Replaces `node::FatalException()` which has a different API across supported versions of Node. For use with [`Nan::TryCatch`](#api_nan_try_catch). + +Signature: + +```c++ +void Nan::FatalException(const Nan::TryCatch& try_catch); +``` + + +### Nan::ErrnoException() + +Replaces `node::ErrnoException()` which has a different API across supported versions of Node. + +Signature: + +```c++ +v8::Local Nan::ErrnoException(int errorno, + const char* syscall = NULL, + const char* message = NULL, + const char* path = NULL); +``` + + + +### Nan::TryCatch + +A simple wrapper around [`v8::TryCatch`](https://v8docs.nodesource.com/node-8.11/d4/dc6/classv8_1_1_try_catch.html) compatible with all supported versions of V8. Can be used as a direct replacement in most cases. See also [`Nan::FatalException()`](#api_nan_fatal_exception) for an internal use compatible with `node::FatalException`. + +Signature: + +```c++ +class Nan::TryCatch { + public: + Nan::TryCatch(); + + bool HasCaught() const; + + bool CanContinue() const; + + v8::Local ReThrow(); + + v8::Local Exception() const; + + // Nan::MaybeLocal for older versions of V8 + v8::MaybeLocal StackTrace() const; + + v8::Local Message() const; + + void Reset(); + + void SetVerbose(bool value); + + void SetCaptureMessage(bool value); +}; +``` + diff --git a/express-server/node_modules/nan/doc/json.md b/express-server/node_modules/nan/doc/json.md new file mode 100644 index 00000000..4fa78dba --- /dev/null +++ b/express-server/node_modules/nan/doc/json.md @@ -0,0 +1,62 @@ +## JSON + +The _JSON_ object provides the c++ versions of the methods offered by the `JSON` object in javascript. V8 exposes these methods via the `v8::JSON` object. + + - Nan::JSON.Parse + - Nan::JSON.Stringify + +Refer to the V8 JSON object in the [V8 documentation](https://v8docs.nodesource.com/node-8.11/da/d6f/classv8_1_1_j_s_o_n.html) for more information about these methods and their arguments. + + + +### Nan::JSON.Parse + +A simple wrapper around [`v8::JSON::Parse`](https://v8docs.nodesource.com/node-8.11/da/d6f/classv8_1_1_j_s_o_n.html#a936310d2540fb630ed37d3ee3ffe4504). + +Definition: + +```c++ +Nan::MaybeLocal Nan::JSON::Parse(v8::Local json_string); +``` + +Use `JSON.Parse(json_string)` to parse a string into a `v8::Value`. + +Example: + +```c++ +v8::Local json_string = Nan::New("{ \"JSON\": \"object\" }").ToLocalChecked(); + +Nan::JSON NanJSON; +Nan::MaybeLocal result = NanJSON.Parse(json_string); +if (!result.IsEmpty()) { + v8::Local val = result.ToLocalChecked(); +} +``` + + + +### Nan::JSON.Stringify + +A simple wrapper around [`v8::JSON::Stringify`](https://v8docs.nodesource.com/node-8.11/da/d6f/classv8_1_1_j_s_o_n.html#a44b255c3531489ce43f6110209138860). + +Definition: + +```c++ +Nan::MaybeLocal Nan::JSON::Stringify(v8::Local json_object, v8::Local gap = v8::Local()); +``` + +Use `JSON.Stringify(value)` to stringify a `v8::Object`. + +Example: + +```c++ +// using `v8::Local val` from the `JSON::Parse` example +v8::Local obj = Nan::To(val).ToLocalChecked(); + +Nan::JSON NanJSON; +Nan::MaybeLocal result = NanJSON.Stringify(obj); +if (!result.IsEmpty()) { + v8::Local stringified = result.ToLocalChecked(); +} +``` + diff --git a/express-server/node_modules/nan/doc/maybe_types.md b/express-server/node_modules/nan/doc/maybe_types.md new file mode 100644 index 00000000..1a9fabf7 --- /dev/null +++ b/express-server/node_modules/nan/doc/maybe_types.md @@ -0,0 +1,583 @@ +## Maybe Types + +The `Nan::MaybeLocal` and `Nan::Maybe` types are monads that encapsulate `v8::Local` handles that _may be empty_. + +* **Maybe Types** + - Nan::MaybeLocal + - Nan::Maybe + - Nan::Nothing + - Nan::Just +* **Maybe Helpers** + - Nan::Call() + - Nan::ToDetailString() + - Nan::ToArrayIndex() + - Nan::Equals() + - Nan::NewInstance() + - Nan::GetFunction() + - Nan::Set() + - Nan::DefineOwnProperty() + - Nan::ForceSet() + - Nan::Get() + - Nan::GetPropertyAttributes() + - Nan::Has() + - Nan::Delete() + - Nan::GetPropertyNames() + - Nan::GetOwnPropertyNames() + - Nan::SetPrototype() + - Nan::ObjectProtoToString() + - Nan::HasOwnProperty() + - Nan::HasRealNamedProperty() + - Nan::HasRealIndexedProperty() + - Nan::HasRealNamedCallbackProperty() + - Nan::GetRealNamedPropertyInPrototypeChain() + - Nan::GetRealNamedProperty() + - Nan::CallAsFunction() + - Nan::CallAsConstructor() + - Nan::GetSourceLine() + - Nan::GetLineNumber() + - Nan::GetStartColumn() + - Nan::GetEndColumn() + - Nan::CloneElementAt() + - Nan::HasPrivate() + - Nan::GetPrivate() + - Nan::SetPrivate() + - Nan::DeletePrivate() + - Nan::MakeMaybe() + + +### Nan::MaybeLocal + +A `Nan::MaybeLocal` is a wrapper around [`v8::Local`](https://v8docs.nodesource.com/node-8.11/de/deb/classv8_1_1_local.html) that enforces a check that determines whether the `v8::Local` is empty before it can be used. + +If an API method returns a `Nan::MaybeLocal`, the API method can potentially fail either because an exception is thrown, or because an exception is pending, e.g. because a previous API call threw an exception that hasn't been caught yet, or because a `v8::TerminateExecution` exception was thrown. In that case, an empty `Nan::MaybeLocal` is returned. + +Definition: + +```c++ +template class Nan::MaybeLocal { + public: + MaybeLocal(); + + template MaybeLocal(v8::Local that); + + bool IsEmpty() const; + + template bool ToLocal(v8::Local *out); + + // Will crash if the MaybeLocal<> is empty. + v8::Local ToLocalChecked(); + + template v8::Local FromMaybe(v8::Local default_value) const; +}; +``` + +See the documentation for [`v8::MaybeLocal`](https://v8docs.nodesource.com/node-8.11/d8/d7d/classv8_1_1_maybe_local.html) for further details. + + +### Nan::Maybe + +A simple `Nan::Maybe` type, representing an object which may or may not have a value, see https://hackage.haskell.org/package/base/docs/Data-Maybe.html. + +If an API method returns a `Nan::Maybe<>`, the API method can potentially fail either because an exception is thrown, or because an exception is pending, e.g. because a previous API call threw an exception that hasn't been caught yet, or because a `v8::TerminateExecution` exception was thrown. In that case, a "Nothing" value is returned. + +Definition: + +```c++ +template class Nan::Maybe { + public: + bool IsNothing() const; + bool IsJust() const; + + // Will crash if the Maybe<> is nothing. + T FromJust(); + + T FromMaybe(const T& default_value); + + bool operator==(const Maybe &other); + + bool operator!=(const Maybe &other); +}; +``` + +See the documentation for [`v8::Maybe`](https://v8docs.nodesource.com/node-8.11/d9/d4b/classv8_1_1_maybe.html) for further details. + + +### Nan::Nothing + +Construct an empty `Nan::Maybe` type representing _nothing_. + +```c++ +template Nan::Maybe Nan::Nothing(); +``` + + +### Nan::Just + +Construct a `Nan::Maybe` type representing _just_ a value. + +```c++ +template Nan::Maybe Nan::Just(const T &t); +``` + + +### Nan::Call() + +A helper method for calling a synchronous [`v8::Function#Call()`](https://v8docs.nodesource.com/node-8.11/d5/d54/classv8_1_1_function.html#a9c3d0e4e13ddd7721fce238aa5b94a11) in a way compatible across supported versions of V8. + +For asynchronous callbacks, use Nan::Callback::Call along with an AsyncResource. + +Signature: + +```c++ +Nan::MaybeLocal Nan::Call(v8::Local fun, v8::Local recv, int argc, v8::Local argv[]); +Nan::MaybeLocal Nan::Call(const Nan::Callback& callback, v8::Local recv, + int argc, v8::Local argv[]); +Nan::MaybeLocal Nan::Call(const Nan::Callback& callback, int argc, v8::Local argv[]); +``` + + + +### Nan::ToDetailString() + +A helper method for calling [`v8::Value#ToDetailString()`](https://v8docs.nodesource.com/node-8.11/dc/d0a/classv8_1_1_value.html#a2f9770296dc2c8d274bc8cc0dca243e5) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::ToDetailString(v8::Local val); +``` + + + +### Nan::ToArrayIndex() + +A helper method for calling [`v8::Value#ToArrayIndex()`](https://v8docs.nodesource.com/node-8.11/dc/d0a/classv8_1_1_value.html#acc5bbef3c805ec458470c0fcd6f13493) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::ToArrayIndex(v8::Local val); +``` + + + +### Nan::Equals() + +A helper method for calling [`v8::Value#Equals()`](https://v8docs.nodesource.com/node-8.11/dc/d0a/classv8_1_1_value.html#a08fba1d776a59bbf6864b25f9152c64b) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::Equals(v8::Local a, v8::Local(b)); +``` + + + +### Nan::NewInstance() + +A helper method for calling [`v8::Function#NewInstance()`](https://v8docs.nodesource.com/node-8.11/d5/d54/classv8_1_1_function.html#ae477558b10c14b76ed00e8dbab44ce5b) and [`v8::ObjectTemplate#NewInstance()`](https://v8docs.nodesource.com/node-8.11/db/d5f/classv8_1_1_object_template.html#ad605a7543cfbc5dab54cdb0883d14ae4) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::NewInstance(v8::Local h); +Nan::MaybeLocal Nan::NewInstance(v8::Local h, int argc, v8::Local argv[]); +Nan::MaybeLocal Nan::NewInstance(v8::Local h); +``` + + + +### Nan::GetFunction() + +A helper method for calling [`v8::FunctionTemplate#GetFunction()`](https://v8docs.nodesource.com/node-8.11/d8/d83/classv8_1_1_function_template.html#a56d904662a86eca78da37d9bb0ed3705) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::GetFunction(v8::Local t); +``` + + + +### Nan::Set() + +A helper method for calling [`v8::Object#Set()`](https://v8docs.nodesource.com/node-8.11/db/d85/classv8_1_1_object.html#a67604ea3734f170c66026064ea808f20) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::Set(v8::Local obj, + v8::Local key, + v8::Local value) +Nan::Maybe Nan::Set(v8::Local obj, + uint32_t index, + v8::Local value); +``` + + + +### Nan::DefineOwnProperty() + +A helper method for calling [`v8::Object#DefineOwnProperty()`](https://v8docs.nodesource.com/node-8.11/db/d85/classv8_1_1_object.html#a6f76b2ed605cb8f9185b92de0033a820) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::DefineOwnProperty(v8::Local obj, + v8::Local key, + v8::Local value, + v8::PropertyAttribute attribs = v8::None); +``` + + + +### Nan::ForceSet() + +Deprecated, use Nan::DefineOwnProperty(). + +A helper method for calling [`v8::Object#ForceSet()`](https://v8docs.nodesource.com/node-0.12/db/d85/classv8_1_1_object.html#acfbdfd7427b516ebdb5c47c4df5ed96c) in a way compatible across supported versions of V8. + +Signature: + +```c++ +NAN_DEPRECATED Nan::Maybe Nan::ForceSet(v8::Local obj, + v8::Local key, + v8::Local value, + v8::PropertyAttribute attribs = v8::None); +``` + + + +### Nan::Get() + +A helper method for calling [`v8::Object#Get()`](https://v8docs.nodesource.com/node-8.11/db/d85/classv8_1_1_object.html#a2565f03e736694f6b1e1cf22a0b4eac2) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::Get(v8::Local obj, + v8::Local key); +Nan::MaybeLocal Nan::Get(v8::Local obj, uint32_t index); +``` + + + +### Nan::GetPropertyAttributes() + +A helper method for calling [`v8::Object#GetPropertyAttributes()`](https://v8docs.nodesource.com/node-8.11/db/d85/classv8_1_1_object.html#a9b898894da3d1db2714fd9325a54fe57) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::GetPropertyAttributes( + v8::Local obj, + v8::Local key); +``` + + + +### Nan::Has() + +A helper method for calling [`v8::Object#Has()`](https://v8docs.nodesource.com/node-8.11/db/d85/classv8_1_1_object.html#ab3c3d89ea7c2f9afd08965bd7299a41d) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::Has(v8::Local obj, v8::Local key); +Nan::Maybe Nan::Has(v8::Local obj, uint32_t index); +``` + + + +### Nan::Delete() + +A helper method for calling [`v8::Object#Delete()`](https://v8docs.nodesource.com/node-8.11/db/d85/classv8_1_1_object.html#a48e4a19b2cedff867eecc73ddb7d377f) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::Delete(v8::Local obj, + v8::Local key); +Nan::Maybe Nan::Delete(v8::Local obj, uint32_t index); +``` + + + +### Nan::GetPropertyNames() + +A helper method for calling [`v8::Object#GetPropertyNames()`](https://v8docs.nodesource.com/node-8.11/db/d85/classv8_1_1_object.html#aced885270cfd2c956367b5eedc7fbfe8) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::GetPropertyNames(v8::Local obj); +``` + + + +### Nan::GetOwnPropertyNames() + +A helper method for calling [`v8::Object#GetOwnPropertyNames()`](https://v8docs.nodesource.com/node-8.11/db/d85/classv8_1_1_object.html#a79a6e4d66049b9aa648ed4dfdb23e6eb) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::GetOwnPropertyNames(v8::Local obj); +``` + + + +### Nan::SetPrototype() + +A helper method for calling [`v8::Object#SetPrototype()`](https://v8docs.nodesource.com/node-8.11/db/d85/classv8_1_1_object.html#a442706b22fceda6e6d1f632122a9a9f4) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::SetPrototype(v8::Local obj, + v8::Local prototype); +``` + + + +### Nan::ObjectProtoToString() + +A helper method for calling [`v8::Object#ObjectProtoToString()`](https://v8docs.nodesource.com/node-8.11/db/d85/classv8_1_1_object.html#ab7a92b4dcf822bef72f6c0ac6fea1f0b) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::ObjectProtoToString(v8::Local obj); +``` + + + +### Nan::HasOwnProperty() + +A helper method for calling [`v8::Object#HasOwnProperty()`](https://v8docs.nodesource.com/node-8.11/db/d85/classv8_1_1_object.html#ab7b7245442ca6de1e1c145ea3fd653ff) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::HasOwnProperty(v8::Local obj, + v8::Local key); +``` + + + +### Nan::HasRealNamedProperty() + +A helper method for calling [`v8::Object#HasRealNamedProperty()`](https://v8docs.nodesource.com/node-8.11/db/d85/classv8_1_1_object.html#ad8b80a59c9eb3c1e6c3cd6c84571f767) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::HasRealNamedProperty(v8::Local obj, + v8::Local key); +``` + + + +### Nan::HasRealIndexedProperty() + +A helper method for calling [`v8::Object#HasRealIndexedProperty()`](https://v8docs.nodesource.com/node-8.11/db/d85/classv8_1_1_object.html#af94fc1135a5e74a2193fb72c3a1b9855) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::HasRealIndexedProperty(v8::Local obj, + uint32_t index); +``` + + + +### Nan::HasRealNamedCallbackProperty() + +A helper method for calling [`v8::Object#HasRealNamedCallbackProperty()`](https://v8docs.nodesource.com/node-8.11/db/d85/classv8_1_1_object.html#af743b7ea132b89f84d34d164d0668811) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::HasRealNamedCallbackProperty( + v8::Local obj, + v8::Local key); +``` + + + +### Nan::GetRealNamedPropertyInPrototypeChain() + +A helper method for calling [`v8::Object#GetRealNamedPropertyInPrototypeChain()`](https://v8docs.nodesource.com/node-8.11/db/d85/classv8_1_1_object.html#a8700b1862e6b4783716964ba4d5e6172) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::GetRealNamedPropertyInPrototypeChain( + v8::Local obj, + v8::Local key); +``` + + + +### Nan::GetRealNamedProperty() + +A helper method for calling [`v8::Object#GetRealNamedProperty()`](https://v8docs.nodesource.com/node-8.11/db/d85/classv8_1_1_object.html#a84471a824576a5994fdd0ffcbf99ccc0) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::GetRealNamedProperty(v8::Local obj, + v8::Local key); +``` + + + +### Nan::CallAsFunction() + +A helper method for calling [`v8::Object#CallAsFunction()`](https://v8docs.nodesource.com/node-8.11/db/d85/classv8_1_1_object.html#ad3ffc36f3dfc3592ce2a96bc047ee2cd) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::CallAsFunction(v8::Local obj, + v8::Local recv, + int argc, + v8::Local argv[]); +``` + + + +### Nan::CallAsConstructor() + +A helper method for calling [`v8::Object#CallAsConstructor()`](https://v8docs.nodesource.com/node-8.11/db/d85/classv8_1_1_object.html#a50d571de50d0b0dfb28795619d07a01b) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::CallAsConstructor(v8::Local obj, + int argc, + v8::Local argv[]); +``` + + + +### Nan::GetSourceLine() + +A helper method for calling [`v8::Message#GetSourceLine()`](https://v8docs.nodesource.com/node-8.11/d9/d28/classv8_1_1_message.html#a849f7a6c41549d83d8159825efccd23a) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::GetSourceLine(v8::Local msg); +``` + + + +### Nan::GetLineNumber() + +A helper method for calling [`v8::Message#GetLineNumber()`](https://v8docs.nodesource.com/node-8.11/d9/d28/classv8_1_1_message.html#adbe46c10a88a6565f2732a2d2adf99b9) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::GetLineNumber(v8::Local msg); +``` + + + +### Nan::GetStartColumn() + +A helper method for calling [`v8::Message#GetStartColumn()`](https://v8docs.nodesource.com/node-8.11/d9/d28/classv8_1_1_message.html#a60ede616ba3822d712e44c7a74487ba6) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::GetStartColumn(v8::Local msg); +``` + + + +### Nan::GetEndColumn() + +A helper method for calling [`v8::Message#GetEndColumn()`](https://v8docs.nodesource.com/node-8.11/d9/d28/classv8_1_1_message.html#aaa004cf19e529da980bc19fcb76d93be) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::GetEndColumn(v8::Local msg); +``` + + + +### Nan::CloneElementAt() + +A helper method for calling [`v8::Array#CloneElementAt()`](https://v8docs.nodesource.com/node-4.8/d3/d32/classv8_1_1_array.html#a1d3a878d4c1c7cae974dd50a1639245e) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::CloneElementAt(v8::Local array, uint32_t index); +``` + + +### Nan::HasPrivate() + +A helper method for calling [`v8::Object#HasPrivate()`](https://v8docs.nodesource.com/node-8.11/db/d85/classv8_1_1_object.html#af68a0b98066cfdeb8f943e98a40ba08d) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::HasPrivate(v8::Local object, v8::Local key); +``` + + +### Nan::GetPrivate() + +A helper method for calling [`v8::Object#GetPrivate()`](https://v8docs.nodesource.com/node-8.11/db/d85/classv8_1_1_object.html#a169f2da506acbec34deadd9149a1925a) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::GetPrivate(v8::Local object, v8::Local key); +``` + + +### Nan::SetPrivate() + +A helper method for calling [`v8::Object#SetPrivate()`](https://v8docs.nodesource.com/node-8.11/db/d85/classv8_1_1_object.html#ace1769b0f3b86bfe9fda1010916360ee) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::SetPrivate(v8::Local object, v8::Local key, v8::Local value); +``` + + +### Nan::DeletePrivate() + +A helper method for calling [`v8::Object#DeletePrivate()`](https://v8docs.nodesource.com/node-8.11/db/d85/classv8_1_1_object.html#a138bb32a304f3982be02ad499693b8fd) in a way compatible across supported versions of V8. + +Signature: + +```c++ +Nan::Maybe Nan::DeletePrivate(v8::Local object, v8::Local key); +``` + + +### Nan::MakeMaybe() + +Wraps a `v8::Local<>` in a `Nan::MaybeLocal<>`. When called with a `Nan::MaybeLocal<>` it just returns its argument. This is useful in generic template code that builds on NAN. + +Synopsis: + +```c++ + MaybeLocal someNumber = MakeMaybe(New(3.141592654)); + MaybeLocal someString = MakeMaybe(New("probably")); +``` + +Signature: + +```c++ +template class MaybeMaybe> +Nan::MaybeLocal Nan::MakeMaybe(MaybeMaybe v); +``` diff --git a/express-server/node_modules/nan/doc/methods.md b/express-server/node_modules/nan/doc/methods.md new file mode 100644 index 00000000..b2b26c38 --- /dev/null +++ b/express-server/node_modules/nan/doc/methods.md @@ -0,0 +1,661 @@ +## JavaScript-accessible methods + +A _template_ is a blueprint for JavaScript functions and objects in a context. You can use a template to wrap C++ functions and data structures within JavaScript objects so that they can be manipulated from JavaScript. See the V8 Embedders Guide section on [Templates](https://github.com/v8/v8/wiki/Embedder%27s-Guide#templates) for further information. + +In order to expose functionality to JavaScript via a template, you must provide it to V8 in a form that it understands. Across the versions of V8 supported by NAN, JavaScript-accessible method signatures vary widely, NAN fully abstracts method declaration and provides you with an interface that is similar to the most recent V8 API but is backward-compatible with older versions that still use the now-deceased `v8::Argument` type. + +* **Method argument types** + - Nan::FunctionCallbackInfo + - Nan::PropertyCallbackInfo + - Nan::ReturnValue +* **Method declarations** + - Method declaration + - Getter declaration + - Setter declaration + - Property getter declaration + - Property setter declaration + - Property enumerator declaration + - Property deleter declaration + - Property query declaration + - Index getter declaration + - Index setter declaration + - Index enumerator declaration + - Index deleter declaration + - Index query declaration +* Method and template helpers + - Nan::SetMethod() + - Nan::SetPrototypeMethod() + - Nan::SetAccessor() + - Nan::SetNamedPropertyHandler() + - Nan::SetIndexedPropertyHandler() + - Nan::SetTemplate() + - Nan::SetPrototypeTemplate() + - Nan::SetInstanceTemplate() + - Nan::SetCallHandler() + - Nan::SetCallAsFunctionHandler() + + +### Nan::FunctionCallbackInfo + +`Nan::FunctionCallbackInfo` should be used in place of [`v8::FunctionCallbackInfo`](https://v8docs.nodesource.com/node-8.11/dd/d0d/classv8_1_1_function_callback_info.html), even with older versions of Node where `v8::FunctionCallbackInfo` does not exist. + +Definition: + +```c++ +template class FunctionCallbackInfo { + public: + ReturnValue GetReturnValue() const; + v8::Local Callee(); // NOTE: Not available in NodeJS >= 10.0.0 + v8::Local Data(); + v8::Local Holder(); + bool IsConstructCall(); + int Length() const; + v8::Local operator[](int i) const; + v8::Local This() const; + v8::Isolate *GetIsolate() const; +}; +``` + +See the [`v8::FunctionCallbackInfo`](https://v8docs.nodesource.com/node-8.11/dd/d0d/classv8_1_1_function_callback_info.html) documentation for usage details on these. See [`Nan::ReturnValue`](#api_nan_return_value) for further information on how to set a return value from methods. + +**Note:** `FunctionCallbackInfo::Callee` is removed in Node.js after `10.0.0` because it is was deprecated in V8. Consider using `info.Data()` to pass any information you need. + + +### Nan::PropertyCallbackInfo + +`Nan::PropertyCallbackInfo` should be used in place of [`v8::PropertyCallbackInfo`](https://v8docs.nodesource.com/node-8.11/d7/dc5/classv8_1_1_property_callback_info.html), even with older versions of Node where `v8::PropertyCallbackInfo` does not exist. + +Definition: + +```c++ +template class PropertyCallbackInfo : public PropertyCallbackInfoBase { + public: + ReturnValue GetReturnValue() const; + v8::Isolate* GetIsolate() const; + v8::Local Data() const; + v8::Local This() const; + v8::Local Holder() const; +}; +``` + +See the [`v8::PropertyCallbackInfo`](https://v8docs.nodesource.com/node-8.11/d7/dc5/classv8_1_1_property_callback_info.html) documentation for usage details on these. See [`Nan::ReturnValue`](#api_nan_return_value) for further information on how to set a return value from property accessor methods. + + +### Nan::ReturnValue + +`Nan::ReturnValue` is used in place of [`v8::ReturnValue`](https://v8docs.nodesource.com/node-8.11/da/da7/classv8_1_1_return_value.html) on both [`Nan::FunctionCallbackInfo`](#api_nan_function_callback_info) and [`Nan::PropertyCallbackInfo`](#api_nan_property_callback_info) as the return type of `GetReturnValue()`. + +Example usage: + +```c++ +void EmptyArray(const Nan::FunctionCallbackInfo& info) { + info.GetReturnValue().Set(Nan::New()); +} +``` + +Definition: + +```c++ +template class ReturnValue { + public: + // Handle setters + template void Set(const v8::Local &handle); + template void Set(const Nan::Global &handle); + + // Fast primitive setters + void Set(bool value); + void Set(double i); + void Set(int32_t i); + void Set(uint32_t i); + + // Fast JS primitive setters + void SetNull(); + void SetUndefined(); + void SetEmptyString(); + + // Convenience getter for isolate + v8::Isolate *GetIsolate() const; +}; +``` + +See the documentation on [`v8::ReturnValue`](https://v8docs.nodesource.com/node-8.11/da/da7/classv8_1_1_return_value.html) for further information on this. + + +### Method declaration + +JavaScript-accessible methods should be declared with the following signature to form a `Nan::FunctionCallback`: + +```c++ +typedef void(*FunctionCallback)(const FunctionCallbackInfo&); +``` + +Example: + +```c++ +void MethodName(const Nan::FunctionCallbackInfo& info) { + ... +} +``` + +You do not need to declare a new `HandleScope` within a method as one is implicitly created for you. + +**Example usage** + +```c++ +// .h: +class Foo : public Nan::ObjectWrap { + ... + + static void Bar(const Nan::FunctionCallbackInfo& info); + static void Baz(const Nan::FunctionCallbackInfo& info); +} + + +// .cc: +void Foo::Bar(const Nan::FunctionCallbackInfo& info) { + ... +} + +void Foo::Baz(const Nan::FunctionCallbackInfo& info) { + ... +} +``` + +A helper macro `NAN_METHOD(methodname)` exists, compatible with NAN v1 method declarations. + +**Example usage with `NAN_METHOD(methodname)`** + +```c++ +// .h: +class Foo : public Nan::ObjectWrap { + ... + + static NAN_METHOD(Bar); + static NAN_METHOD(Baz); +} + + +// .cc: +NAN_METHOD(Foo::Bar) { + ... +} + +NAN_METHOD(Foo::Baz) { + ... +} +``` + +Use [`Nan::SetPrototypeMethod`](#api_nan_set_prototype_method) to attach a method to a JavaScript function prototype or [`Nan::SetMethod`](#api_nan_set_method) to attach a method directly on a JavaScript object. + + +### Getter declaration + +JavaScript-accessible getters should be declared with the following signature to form a `Nan::GetterCallback`: + +```c++ +typedef void(*GetterCallback)(v8::Local, + const PropertyCallbackInfo&); +``` + +Example: + +```c++ +void GetterName(v8::Local property, + const Nan::PropertyCallbackInfo& info) { + ... +} +``` + +You do not need to declare a new `HandleScope` within a getter as one is implicitly created for you. + +A helper macro `NAN_GETTER(methodname)` exists, compatible with NAN v1 method declarations. + +Also see the V8 Embedders Guide documentation on [Accessors](https://developers.google.com/v8/embed#accesssors). + + +### Setter declaration + +JavaScript-accessible setters should be declared with the following signature to form a Nan::SetterCallback: + +```c++ +typedef void(*SetterCallback)(v8::Local, + v8::Local, + const PropertyCallbackInfo&); +``` + +Example: + +```c++ +void SetterName(v8::Local property, + v8::Local value, + const Nan::PropertyCallbackInfo& info) { + ... +} +``` + +You do not need to declare a new `HandleScope` within a setter as one is implicitly created for you. + +A helper macro `NAN_SETTER(methodname)` exists, compatible with NAN v1 method declarations. + +Also see the V8 Embedders Guide documentation on [Accessors](https://developers.google.com/v8/embed#accesssors). + + +### Property getter declaration + +JavaScript-accessible property getters should be declared with the following signature to form a Nan::PropertyGetterCallback: + +```c++ +typedef void(*PropertyGetterCallback)(v8::Local, + const PropertyCallbackInfo&); +``` + +Example: + +```c++ +void PropertyGetterName(v8::Local property, + const Nan::PropertyCallbackInfo& info) { + ... +} +``` + +You do not need to declare a new `HandleScope` within a property getter as one is implicitly created for you. + +A helper macro `NAN_PROPERTY_GETTER(methodname)` exists, compatible with NAN v1 method declarations. + +Also see the V8 Embedders Guide documentation on named property [Interceptors](https://developers.google.com/v8/embed#interceptors). + + +### Property setter declaration + +JavaScript-accessible property setters should be declared with the following signature to form a Nan::PropertySetterCallback: + +```c++ +typedef void(*PropertySetterCallback)(v8::Local, + v8::Local, + const PropertyCallbackInfo&); +``` + +Example: + +```c++ +void PropertySetterName(v8::Local property, + v8::Local value, + const Nan::PropertyCallbackInfo& info); +``` + +You do not need to declare a new `HandleScope` within a property setter as one is implicitly created for you. + +A helper macro `NAN_PROPERTY_SETTER(methodname)` exists, compatible with NAN v1 method declarations. + +Also see the V8 Embedders Guide documentation on named property [Interceptors](https://developers.google.com/v8/embed#interceptors). + + +### Property enumerator declaration + +JavaScript-accessible property enumerators should be declared with the following signature to form a Nan::PropertyEnumeratorCallback: + +```c++ +typedef void(*PropertyEnumeratorCallback)(const PropertyCallbackInfo&); +``` + +Example: + +```c++ +void PropertyEnumeratorName(const Nan::PropertyCallbackInfo& info); +``` + +You do not need to declare a new `HandleScope` within a property enumerator as one is implicitly created for you. + +A helper macro `NAN_PROPERTY_ENUMERATOR(methodname)` exists, compatible with NAN v1 method declarations. + +Also see the V8 Embedders Guide documentation on named property [Interceptors](https://developers.google.com/v8/embed#interceptors). + + +### Property deleter declaration + +JavaScript-accessible property deleters should be declared with the following signature to form a Nan::PropertyDeleterCallback: + +```c++ +typedef void(*PropertyDeleterCallback)(v8::Local, + const PropertyCallbackInfo&); +``` + +Example: + +```c++ +void PropertyDeleterName(v8::Local property, + const Nan::PropertyCallbackInfo& info); +``` + +You do not need to declare a new `HandleScope` within a property deleter as one is implicitly created for you. + +A helper macro `NAN_PROPERTY_DELETER(methodname)` exists, compatible with NAN v1 method declarations. + +Also see the V8 Embedders Guide documentation on named property [Interceptors](https://developers.google.com/v8/embed#interceptors). + + +### Property query declaration + +JavaScript-accessible property query methods should be declared with the following signature to form a Nan::PropertyQueryCallback: + +```c++ +typedef void(*PropertyQueryCallback)(v8::Local, + const PropertyCallbackInfo&); +``` + +Example: + +```c++ +void PropertyQueryName(v8::Local property, + const Nan::PropertyCallbackInfo& info); +``` + +You do not need to declare a new `HandleScope` within a property query method as one is implicitly created for you. + +A helper macro `NAN_PROPERTY_QUERY(methodname)` exists, compatible with NAN v1 method declarations. + +Also see the V8 Embedders Guide documentation on named property [Interceptors](https://developers.google.com/v8/embed#interceptors). + + +### Index getter declaration + +JavaScript-accessible index getter methods should be declared with the following signature to form a Nan::IndexGetterCallback: + +```c++ +typedef void(*IndexGetterCallback)(uint32_t, + const PropertyCallbackInfo&); +``` + +Example: + +```c++ +void IndexGetterName(uint32_t index, const PropertyCallbackInfo& info); +``` + +You do not need to declare a new `HandleScope` within a index getter as one is implicitly created for you. + +A helper macro `NAN_INDEX_GETTER(methodname)` exists, compatible with NAN v1 method declarations. + +Also see the V8 Embedders Guide documentation on indexed property [Interceptors](https://developers.google.com/v8/embed#interceptors). + + +### Index setter declaration + +JavaScript-accessible index setter methods should be declared with the following signature to form a Nan::IndexSetterCallback: + +```c++ +typedef void(*IndexSetterCallback)(uint32_t, + v8::Local, + const PropertyCallbackInfo&); +``` + +Example: + +```c++ +void IndexSetterName(uint32_t index, + v8::Local value, + const PropertyCallbackInfo& info); +``` + +You do not need to declare a new `HandleScope` within a index setter as one is implicitly created for you. + +A helper macro `NAN_INDEX_SETTER(methodname)` exists, compatible with NAN v1 method declarations. + +Also see the V8 Embedders Guide documentation on indexed property [Interceptors](https://developers.google.com/v8/embed#interceptors). + + +### Index enumerator declaration + +JavaScript-accessible index enumerator methods should be declared with the following signature to form a Nan::IndexEnumeratorCallback: + +```c++ +typedef void(*IndexEnumeratorCallback)(const PropertyCallbackInfo&); +``` + +Example: + +```c++ +void IndexEnumeratorName(const PropertyCallbackInfo& info); +``` + +You do not need to declare a new `HandleScope` within a index enumerator as one is implicitly created for you. + +A helper macro `NAN_INDEX_ENUMERATOR(methodname)` exists, compatible with NAN v1 method declarations. + +Also see the V8 Embedders Guide documentation on indexed property [Interceptors](https://developers.google.com/v8/embed#interceptors). + + +### Index deleter declaration + +JavaScript-accessible index deleter methods should be declared with the following signature to form a Nan::IndexDeleterCallback: + +```c++ +typedef void(*IndexDeleterCallback)(uint32_t, + const PropertyCallbackInfo&); +``` + +Example: + +```c++ +void IndexDeleterName(uint32_t index, const PropertyCallbackInfo& info); +``` + +You do not need to declare a new `HandleScope` within a index deleter as one is implicitly created for you. + +A helper macro `NAN_INDEX_DELETER(methodname)` exists, compatible with NAN v1 method declarations. + +Also see the V8 Embedders Guide documentation on indexed property [Interceptors](https://developers.google.com/v8/embed#interceptors). + + +### Index query declaration + +JavaScript-accessible index query methods should be declared with the following signature to form a Nan::IndexQueryCallback: + +```c++ +typedef void(*IndexQueryCallback)(uint32_t, + const PropertyCallbackInfo&); +``` + +Example: + +```c++ +void IndexQueryName(uint32_t index, const PropertyCallbackInfo& info); +``` + +You do not need to declare a new `HandleScope` within a index query method as one is implicitly created for you. + +A helper macro `NAN_INDEX_QUERY(methodname)` exists, compatible with NAN v1 method declarations. + +Also see the V8 Embedders Guide documentation on indexed property [Interceptors](https://developers.google.com/v8/embed#interceptors). + + +### Nan::SetMethod() + +Sets a method with a given name directly on a JavaScript object where the method has the `Nan::FunctionCallback` signature (see Method declaration). + +Signature: + +```c++ +void Nan::SetMethod(v8::Local recv, + const char *name, + Nan::FunctionCallback callback) +void Nan::SetMethod(v8::Local templ, + const char *name, + Nan::FunctionCallback callback) +``` + + +### Nan::SetPrototypeMethod() + +Sets a method with a given name on a `FunctionTemplate`'s prototype where the method has the `Nan::FunctionCallback` signature (see Method declaration). + +Signature: + +```c++ +void Nan::SetPrototypeMethod(v8::Local recv, + const char* name, + Nan::FunctionCallback callback) +``` + + +### Nan::SetAccessor() + +Sets getters and setters for a property with a given name on an `ObjectTemplate` or a plain `Object`. Accepts getters with the `Nan::GetterCallback` signature (see Getter declaration) and setters with the `Nan::SetterCallback` signature (see Setter declaration). + +Signature: + +```c++ +void SetAccessor(v8::Local tpl, + v8::Local name, + Nan::GetterCallback getter, + Nan::SetterCallback setter = 0, + v8::Local data = v8::Local(), + v8::AccessControl settings = v8::DEFAULT, + v8::PropertyAttribute attribute = v8::None, + imp::Sig signature = imp::Sig()); +bool SetAccessor(v8::Local obj, + v8::Local name, + Nan::GetterCallback getter, + Nan::SetterCallback setter = 0, + v8::Local data = v8::Local(), + v8::AccessControl settings = v8::DEFAULT, + v8::PropertyAttribute attribute = v8::None) +``` + +See the V8 [`ObjectTemplate#SetAccessor()`](https://v8docs.nodesource.com/node-8.11/db/d5f/classv8_1_1_object_template.html#aca0ed196f8a9adb1f68b1aadb6c9cd77) and [`Object#SetAccessor()`](https://v8docs.nodesource.com/node-8.11/db/d85/classv8_1_1_object.html#ae91b3b56b357f285288c89fbddc46d1b) for further information about how to use `Nan::SetAccessor()`. + + +### Nan::SetNamedPropertyHandler() + +Sets named property getters, setters, query, deleter and enumerator methods on an `ObjectTemplate`. Accepts: + +* Property getters with the `Nan::PropertyGetterCallback` signature (see Property getter declaration) +* Property setters with the `Nan::PropertySetterCallback` signature (see Property setter declaration) +* Property query methods with the `Nan::PropertyQueryCallback` signature (see Property query declaration) +* Property deleters with the `Nan::PropertyDeleterCallback` signature (see Property deleter declaration) +* Property enumerators with the `Nan::PropertyEnumeratorCallback` signature (see Property enumerator declaration) + +Signature: + +```c++ +void SetNamedPropertyHandler(v8::Local tpl, + Nan::PropertyGetterCallback getter, + Nan::PropertySetterCallback setter = 0, + Nan::PropertyQueryCallback query = 0, + Nan::PropertyDeleterCallback deleter = 0, + Nan::PropertyEnumeratorCallback enumerator = 0, + v8::Local data = v8::Local()) +``` + +See the V8 [`ObjectTemplate#SetNamedPropertyHandler()`](https://v8docs.nodesource.com/node-8.11/db/d5f/classv8_1_1_object_template.html#a33b3ebd7de641f6cc6414b7de01fc1c7) for further information about how to use `Nan::SetNamedPropertyHandler()`. + + +### Nan::SetIndexedPropertyHandler() + +Sets indexed property getters, setters, query, deleter and enumerator methods on an `ObjectTemplate`. Accepts: + +* Indexed property getters with the `Nan::IndexGetterCallback` signature (see Index getter declaration) +* Indexed property setters with the `Nan::IndexSetterCallback` signature (see Index setter declaration) +* Indexed property query methods with the `Nan::IndexQueryCallback` signature (see Index query declaration) +* Indexed property deleters with the `Nan::IndexDeleterCallback` signature (see Index deleter declaration) +* Indexed property enumerators with the `Nan::IndexEnumeratorCallback` signature (see Index enumerator declaration) + +Signature: + +```c++ +void SetIndexedPropertyHandler(v8::Local tpl, + Nan::IndexGetterCallback getter, + Nan::IndexSetterCallback setter = 0, + Nan::IndexQueryCallback query = 0, + Nan::IndexDeleterCallback deleter = 0, + Nan::IndexEnumeratorCallback enumerator = 0, + v8::Local data = v8::Local()) +``` + +See the V8 [`ObjectTemplate#SetIndexedPropertyHandler()`](https://v8docs.nodesource.com/node-8.11/db/d5f/classv8_1_1_object_template.html#ac89f06d634add0e890452033f7d17ff1) for further information about how to use `Nan::SetIndexedPropertyHandler()`. + + +### Nan::SetTemplate() + +Adds properties on an `Object`'s or `Function`'s template. + +Signature: + +```c++ +void Nan::SetTemplate(v8::Local templ, + const char *name, + v8::Local value); +void Nan::SetTemplate(v8::Local templ, + v8::Local name, + v8::Local value, + v8::PropertyAttribute attributes) +``` + +Calls the `Template`'s [`Set()`](https://v8docs.nodesource.com/node-8.11/db/df7/classv8_1_1_template.html#ae3fbaff137557aa6a0233bc7e52214ac). + + +### Nan::SetPrototypeTemplate() + +Adds properties on an `Object`'s or `Function`'s prototype template. + +Signature: + +```c++ +void Nan::SetPrototypeTemplate(v8::Local templ, + const char *name, + v8::Local value); +void Nan::SetPrototypeTemplate(v8::Local templ, + v8::Local name, + v8::Local value, + v8::PropertyAttribute attributes) +``` + +Calls the `FunctionTemplate`'s _PrototypeTemplate's_ [`Set()`](https://v8docs.nodesource.com/node-8.11/db/df7/classv8_1_1_template.html#a2db6a56597bf23c59659c0659e564ddf). + + +### Nan::SetInstanceTemplate() + +Use to add instance properties on `FunctionTemplate`'s. + +Signature: + +```c++ +void Nan::SetInstanceTemplate(v8::Local templ, + const char *name, + v8::Local value); +void Nan::SetInstanceTemplate(v8::Local templ, + v8::Local name, + v8::Local value, + v8::PropertyAttribute attributes) +``` + +Calls the `FunctionTemplate`'s _InstanceTemplate's_ [`Set()`](https://v8docs.nodesource.com/node-8.11/db/df7/classv8_1_1_template.html#a2db6a56597bf23c59659c0659e564ddf). + + +### Nan::SetCallHandler() + +Set the call-handler callback for a `v8::FunctionTemplate`. +This callback is called whenever the function created from this FunctionTemplate is called. + +Signature: + +```c++ +void Nan::SetCallHandler(v8::Local templ, Nan::FunctionCallback callback, v8::Local data = v8::Local()) +``` + +Calls the `FunctionTemplate`'s [`SetCallHandler()`](https://v8docs.nodesource.com/node-8.11/d8/d83/classv8_1_1_function_template.html#ab7574b298db3c27fbc2ed465c08ea2f8). + + +### Nan::SetCallAsFunctionHandler() + +Sets the callback to be used when calling instances created from the `v8::ObjectTemplate` as a function. +If no callback is set, instances behave like normal JavaScript objects that cannot be called as a function. + +Signature: + +```c++ +void Nan::SetCallAsFunctionHandler(v8::Local templ, Nan::FunctionCallback callback, v8::Local data = v8::Local()) +``` + +Calls the `ObjectTemplate`'s [`SetCallAsFunctionHandler()`](https://v8docs.nodesource.com/node-8.11/db/d5f/classv8_1_1_object_template.html#a5e9612fc80bf6db8f2da199b9b0bd04e). + diff --git a/express-server/node_modules/nan/doc/new.md b/express-server/node_modules/nan/doc/new.md new file mode 100644 index 00000000..359df435 --- /dev/null +++ b/express-server/node_modules/nan/doc/new.md @@ -0,0 +1,147 @@ +## New + +NAN provides a `Nan::New()` helper for the creation of new JavaScript objects in a way that's compatible across the supported versions of V8. + + - Nan::New() + - Nan::Undefined() + - Nan::Null() + - Nan::True() + - Nan::False() + - Nan::EmptyString() + + + +### Nan::New() + +`Nan::New()` should be used to instantiate new JavaScript objects. + +Refer to the specific V8 type in the [V8 documentation](https://v8docs.nodesource.com/node-8.11/d1/d83/classv8_1_1_data.html) for information on the types of arguments required for instantiation. + +Signatures: + +Return types are mostly omitted from the signatures for simplicity. In most cases the type will be contained within a `v8::Local`. The following types will be contained within a `Nan::MaybeLocal`: `v8::String`, `v8::Date`, `v8::RegExp`, `v8::Script`, `v8::UnboundScript`. + +Empty objects: + +```c++ +Nan::New(); +``` + +Generic single and multiple-argument: + +```c++ +Nan::New(A0 arg0); +Nan::New(A0 arg0, A1 arg1); +Nan::New(A0 arg0, A1 arg1, A2 arg2); +Nan::New(A0 arg0, A1 arg1, A2 arg2, A3 arg3); +``` + +For creating `v8::FunctionTemplate` and `v8::Function` objects: + +_The definition of `Nan::FunctionCallback` can be found in the [Method declaration](./methods.md#api_nan_method) documentation._ + +```c++ +Nan::New(Nan::FunctionCallback callback, + v8::Local data = v8::Local()); +Nan::New(Nan::FunctionCallback callback, + v8::Local data = v8::Local(), + A2 a2 = A2()); +``` + +Native number types: + +```c++ +v8::Local Nan::New(bool value); +v8::Local Nan::New(int32_t value); +v8::Local Nan::New(uint32_t value); +v8::Local Nan::New(double value); +``` + +String types: + +```c++ +Nan::MaybeLocal Nan::New(std::string const& value); +Nan::MaybeLocal Nan::New(const char * value, int length); +Nan::MaybeLocal Nan::New(const char * value); +Nan::MaybeLocal Nan::New(const uint16_t * value); +Nan::MaybeLocal Nan::New(const uint16_t * value, int length); +``` + +Specialized types: + +```c++ +v8::Local Nan::New(v8::String::ExternalStringResource * value); +v8::Local Nan::New(Nan::ExternalOneByteStringResource * value); +v8::Local Nan::New(v8::Local pattern, v8::RegExp::Flags flags); +``` + +Note that `Nan::ExternalOneByteStringResource` maps to [`v8::String::ExternalOneByteStringResource`](https://v8docs.nodesource.com/node-8.11/d9/db3/classv8_1_1_string_1_1_external_one_byte_string_resource.html), and `v8::String::ExternalAsciiStringResource` in older versions of V8. + + + +### Nan::Undefined() + +A helper method to reference the `v8::Undefined` object in a way that is compatible across all supported versions of V8. + +Signature: + +```c++ +v8::Local Nan::Undefined() +``` + + +### Nan::Null() + +A helper method to reference the `v8::Null` object in a way that is compatible across all supported versions of V8. + +Signature: + +```c++ +v8::Local Nan::Null() +``` + + +### Nan::True() + +A helper method to reference the `v8::Boolean` object representing the `true` value in a way that is compatible across all supported versions of V8. + +Signature: + +```c++ +v8::Local Nan::True() +``` + + +### Nan::False() + +A helper method to reference the `v8::Boolean` object representing the `false` value in a way that is compatible across all supported versions of V8. + +Signature: + +```c++ +v8::Local Nan::False() +``` + + +### Nan::EmptyString() + +Call [`v8::String::Empty`](https://v8docs.nodesource.com/node-8.11/d2/db3/classv8_1_1_string.html#a7c1bc8886115d7ee46f1d571dd6ebc6d) to reference the empty string in a way that is compatible across all supported versions of V8. + +Signature: + +```c++ +v8::Local Nan::EmptyString() +``` + + + +### Nan::NewOneByteString() + +An implementation of [`v8::String::NewFromOneByte()`](https://v8docs.nodesource.com/node-8.11/d2/db3/classv8_1_1_string.html#a5264d50b96d2c896ce525a734dc10f09) provided for consistent availability and API across supported versions of V8. Allocates a new string from Latin-1 data. + +Signature: + +```c++ +Nan::MaybeLocal Nan::NewOneByteString(const uint8_t * value, + int length = -1) +``` diff --git a/express-server/node_modules/nan/doc/node_misc.md b/express-server/node_modules/nan/doc/node_misc.md new file mode 100644 index 00000000..17578e34 --- /dev/null +++ b/express-server/node_modules/nan/doc/node_misc.md @@ -0,0 +1,123 @@ +## Miscellaneous Node Helpers + + - Nan::AsyncResource + - Nan::MakeCallback() + - NAN_MODULE_INIT() + - Nan::Export() + + +### Nan::AsyncResource + +This class is analogous to the `AsyncResource` JavaScript class exposed by Node's [async_hooks][] API. + +When calling back into JavaScript asynchronously, special care must be taken to ensure that the runtime can properly track +async hops. `Nan::AsyncResource` is a class that provides an RAII wrapper around `node::EmitAsyncInit`, `node::EmitAsyncDestroy`, +and `node::MakeCallback`. Using this mechanism to call back into JavaScript, as opposed to `Nan::MakeCallback` or +`v8::Function::Call` ensures that the callback is executed in the correct async context. This ensures that async mechanisms +such as domains and [async_hooks][] function correctly. + +Definition: + +```c++ +class AsyncResource { + public: + AsyncResource(v8::Local name, + v8::Local resource = New()); + AsyncResource(const char* name, + v8::Local resource = New()); + ~AsyncResource(); + + v8::MaybeLocal runInAsyncScope(v8::Local target, + v8::Local func, + int argc, + v8::Local* argv); + v8::MaybeLocal runInAsyncScope(v8::Local target, + v8::Local symbol, + int argc, + v8::Local* argv); + v8::MaybeLocal runInAsyncScope(v8::Local target, + const char* method, + int argc, + v8::Local* argv); +}; +``` + +* `name`: Identifier for the kind of resource that is being provided for diagnostics information exposed by the [async_hooks][] + API. This will be passed to the possible `init` hook as the `type`. To avoid name collisions with other modules we recommend + that the name include the name of the owning module as a prefix. For example `mysql` module could use something like + `mysql:batch-db-query-resource`. +* `resource`: An optional object associated with the async work that will be passed to the possible [async_hooks][] + `init` hook. If this parameter is omitted, or an empty handle is provided, this object will be created automatically. +* When calling JS on behalf of this resource, one can use `runInAsyncScope`. This will ensure that the callback runs in the + correct async execution context. +* `AsyncDestroy` is automatically called when an AsyncResource object is destroyed. + +For more details, see the Node [async_hooks][] documentation. You might also want to take a look at the documentation for the +[N-API counterpart][napi]. For example usage, see the `asyncresource.cpp` example in the `test/cpp` directory. + + +### Nan::MakeCallback() + +Deprecated wrappers around the legacy `node::MakeCallback()` APIs. Node.js 10+ +has deprecated these legacy APIs as they do not provide a mechanism to preserve +async context. + +We recommend that you use the `AsyncResource` class and `AsyncResource::runInAsyncScope` instead of using `Nan::MakeCallback` or +`v8::Function#Call()` directly. `AsyncResource` properly takes care of running the callback in the correct async execution +context – something that is essential for functionality like domains, async_hooks and async debugging. + +Signatures: + +```c++ +NAN_DEPRECATED +v8::Local Nan::MakeCallback(v8::Local target, + v8::Local func, + int argc, + v8::Local* argv); +NAN_DEPRECATED +v8::Local Nan::MakeCallback(v8::Local target, + v8::Local symbol, + int argc, + v8::Local* argv); +NAN_DEPRECATED +v8::Local Nan::MakeCallback(v8::Local target, + const char* method, + int argc, + v8::Local* argv); +``` + + + +### NAN_MODULE_INIT() + +Used to define the entry point function to a Node add-on. Creates a function with a given `name` that receives a `target` object representing the equivalent of the JavaScript `exports` object. + +See example below. + + +### Nan::Export() + +A simple helper to register a `v8::FunctionTemplate` from a JavaScript-accessible method (see [Methods](./methods.md)) as a property on an object. Can be used in a way similar to assigning properties to `module.exports` in JavaScript. + +Signature: + +```c++ +void Export(v8::Local target, const char *name, Nan::FunctionCallback f) +``` + +Also available as the shortcut `NAN_EXPORT` macro. + +Example: + +```c++ +NAN_METHOD(Foo) { + ... +} + +NAN_MODULE_INIT(Init) { + NAN_EXPORT(target, Foo); +} +``` + +[async_hooks]: https://nodejs.org/dist/latest-v9.x/docs/api/async_hooks.html +[napi]: https://nodejs.org/dist/latest-v9.x/docs/api/n-api.html#n_api_custom_asynchronous_operations diff --git a/express-server/node_modules/nan/doc/object_wrappers.md b/express-server/node_modules/nan/doc/object_wrappers.md new file mode 100644 index 00000000..08dd6b55 --- /dev/null +++ b/express-server/node_modules/nan/doc/object_wrappers.md @@ -0,0 +1,263 @@ +## Object Wrappers + +The `ObjectWrap` class can be used to make wrapped C++ objects and a factory of wrapped objects. + + - Nan::ObjectWrap + + + +### Nan::ObjectWrap() + +A reimplementation of `node::ObjectWrap` that adds some API not present in older versions of Node. Should be preferred over `node::ObjectWrap` in all cases for consistency. + +Definition: + +```c++ +class ObjectWrap { + public: + ObjectWrap(); + + virtual ~ObjectWrap(); + + template + static inline T* Unwrap(v8::Local handle); + + inline v8::Local handle(); + + inline Nan::Persistent& persistent(); + + protected: + inline void Wrap(v8::Local handle); + + inline void MakeWeak(); + + /* Ref() marks the object as being attached to an event loop. + * Refed objects will not be garbage collected, even if + * all references are lost. + */ + virtual void Ref(); + + /* Unref() marks an object as detached from the event loop. This is its + * default state. When an object with a "weak" reference changes from + * attached to detached state it will be freed. Be careful not to access + * the object after making this call as it might be gone! + * (A "weak reference" means an object that only has a + * persistant handle.) + * + * DO NOT CALL THIS FROM DESTRUCTOR + */ + virtual void Unref(); + + int refs_; // ro +}; +``` + +See the Node documentation on [Wrapping C++ Objects](https://nodejs.org/api/addons.html#addons_wrapping_c_objects) for more details. + +### This vs. Holder + +When calling `Unwrap`, it is important that the argument is indeed some JavaScript object which got wrapped by a `Wrap` call for this class or any derived class. +The `Signature` installed by [`Nan::SetPrototypeMethod()`](methods.md#api_nan_set_prototype_method) does ensure that `info.Holder()` is just such an instance. +In Node 0.12 and later, `info.This()` will also be of such a type, since otherwise the invocation will get rejected. +However, in Node 0.10 and before it was possible to invoke a method on a JavaScript object which just had the extension type in its prototype chain. +In such a situation, calling `Unwrap` on `info.This()` will likely lead to a failed assertion causing a crash, but could lead to even more serious corruption. + +On the other hand, calling `Unwrap` in an [accessor](methods.md#api_nan_set_accessor) should not use `Holder()` if the accessor is defined on the prototype. +So either define your accessors on the instance template, +or use `This()` after verifying that it is indeed a valid object. + +### Examples + +#### Basic + +```c++ +class MyObject : public Nan::ObjectWrap { + public: + static NAN_MODULE_INIT(Init) { + v8::Local tpl = Nan::New(New); + tpl->SetClassName(Nan::New("MyObject").ToLocalChecked()); + tpl->InstanceTemplate()->SetInternalFieldCount(1); + + Nan::SetPrototypeMethod(tpl, "getHandle", GetHandle); + Nan::SetPrototypeMethod(tpl, "getValue", GetValue); + + constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked()); + Nan::Set(target, Nan::New("MyObject").ToLocalChecked(), + Nan::GetFunction(tpl).ToLocalChecked()); + } + + private: + explicit MyObject(double value = 0) : value_(value) {} + ~MyObject() {} + + static NAN_METHOD(New) { + if (info.IsConstructCall()) { + double value = info[0]->IsUndefined() ? 0 : Nan::To(info[0]).FromJust(); + MyObject *obj = new MyObject(value); + obj->Wrap(info.This()); + info.GetReturnValue().Set(info.This()); + } else { + const int argc = 1; + v8::Local argv[argc] = {info[0]}; + v8::Local cons = Nan::New(constructor()); + info.GetReturnValue().Set(Nan::NewInstance(cons, argc, argv).ToLocalChecked()); + } + } + + static NAN_METHOD(GetHandle) { + MyObject* obj = Nan::ObjectWrap::Unwrap(info.Holder()); + info.GetReturnValue().Set(obj->handle()); + } + + static NAN_METHOD(GetValue) { + MyObject* obj = Nan::ObjectWrap::Unwrap(info.Holder()); + info.GetReturnValue().Set(obj->value_); + } + + static inline Nan::Persistent & constructor() { + static Nan::Persistent my_constructor; + return my_constructor; + } + + double value_; +}; + +NODE_MODULE(objectwrapper, MyObject::Init) +``` + +To use in Javascript: + +```Javascript +var objectwrapper = require('bindings')('objectwrapper'); + +var obj = new objectwrapper.MyObject(5); +console.log('Should be 5: ' + obj.getValue()); +``` + +#### Factory of wrapped objects + +```c++ +class MyFactoryObject : public Nan::ObjectWrap { + public: + static NAN_MODULE_INIT(Init) { + v8::Local tpl = Nan::New(New); + tpl->InstanceTemplate()->SetInternalFieldCount(1); + + Nan::SetPrototypeMethod(tpl, "getValue", GetValue); + + constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked()); + } + + static NAN_METHOD(NewInstance) { + v8::Local cons = Nan::New(constructor()); + double value = info[0]->IsNumber() ? Nan::To(info[0]).FromJust() : 0; + const int argc = 1; + v8::Local argv[1] = {Nan::New(value)}; + info.GetReturnValue().Set(Nan::NewInstance(cons, argc, argv).ToLocalChecked()); + } + + // Needed for the next example: + inline double value() const { + return value_; + } + + private: + explicit MyFactoryObject(double value = 0) : value_(value) {} + ~MyFactoryObject() {} + + static NAN_METHOD(New) { + if (info.IsConstructCall()) { + double value = info[0]->IsNumber() ? Nan::To(info[0]).FromJust() : 0; + MyFactoryObject * obj = new MyFactoryObject(value); + obj->Wrap(info.This()); + info.GetReturnValue().Set(info.This()); + } else { + const int argc = 1; + v8::Local argv[argc] = {info[0]}; + v8::Local cons = Nan::New(constructor()); + info.GetReturnValue().Set(Nan::NewInstance(cons, argc, argv).ToLocalChecked()); + } + } + + static NAN_METHOD(GetValue) { + MyFactoryObject* obj = ObjectWrap::Unwrap(info.Holder()); + info.GetReturnValue().Set(obj->value_); + } + + static inline Nan::Persistent & constructor() { + static Nan::Persistent my_constructor; + return my_constructor; + } + + double value_; +}; + +NAN_MODULE_INIT(Init) { + MyFactoryObject::Init(target); + Nan::Set(target, + Nan::New("newFactoryObjectInstance").ToLocalChecked(), + Nan::GetFunction( + Nan::New(MyFactoryObject::NewInstance)).ToLocalChecked() + ); +} + +NODE_MODULE(wrappedobjectfactory, Init) +``` + +To use in Javascript: + +```Javascript +var wrappedobjectfactory = require('bindings')('wrappedobjectfactory'); + +var obj = wrappedobjectfactory.newFactoryObjectInstance(10); +console.log('Should be 10: ' + obj.getValue()); +``` + +#### Passing wrapped objects around + +Use the `MyFactoryObject` class above along with the following: + +```c++ +static NAN_METHOD(Sum) { + Nan::MaybeLocal maybe1 = Nan::To(info[0]); + Nan::MaybeLocal maybe2 = Nan::To(info[1]); + + // Quick check: + if (maybe1.IsEmpty() || maybe2.IsEmpty()) { + // return value is undefined by default + return; + } + + MyFactoryObject* obj1 = + Nan::ObjectWrap::Unwrap(maybe1.ToLocalChecked()); + MyFactoryObject* obj2 = + Nan::ObjectWrap::Unwrap(maybe2.ToLocalChecked()); + + info.GetReturnValue().Set(Nan::New(obj1->value() + obj2->value())); +} + +NAN_MODULE_INIT(Init) { + MyFactoryObject::Init(target); + Nan::Set(target, + Nan::New("newFactoryObjectInstance").ToLocalChecked(), + Nan::GetFunction( + Nan::New(MyFactoryObject::NewInstance)).ToLocalChecked() + ); + Nan::Set(target, + Nan::New("sum").ToLocalChecked(), + Nan::GetFunction(Nan::New(Sum)).ToLocalChecked() + ); +} + +NODE_MODULE(myaddon, Init) +``` + +To use in Javascript: + +```Javascript +var myaddon = require('bindings')('myaddon'); + +var obj1 = myaddon.newFactoryObjectInstance(5); +var obj2 = myaddon.newFactoryObjectInstance(10); +console.log('sum of object values: ' + myaddon.sum(obj1, obj2)); +``` diff --git a/express-server/node_modules/nan/doc/persistent.md b/express-server/node_modules/nan/doc/persistent.md new file mode 100644 index 00000000..bec9c3f3 --- /dev/null +++ b/express-server/node_modules/nan/doc/persistent.md @@ -0,0 +1,296 @@ +## Persistent references + +An object reference that is independent of any `HandleScope` is a _persistent_ reference. Where a `Local` handle only lives as long as the `HandleScope` in which it was allocated, a `Persistent` handle remains valid until it is explicitly disposed. + +Due to the evolution of the V8 API, it is necessary for NAN to provide a wrapper implementation of the `Persistent` classes to supply compatibility across the V8 versions supported. + + - Nan::PersistentBase & v8::PersistentBase + - Nan::NonCopyablePersistentTraits & v8::NonCopyablePersistentTraits + - Nan::CopyablePersistentTraits & v8::CopyablePersistentTraits + - Nan::Persistent + - Nan::Global + - Nan::WeakCallbackInfo + - Nan::WeakCallbackType + +Also see the V8 Embedders Guide section on [Handles and Garbage Collection](https://developers.google.com/v8/embed#handles). + + +### Nan::PersistentBase & v8::PersistentBase + +A persistent handle contains a reference to a storage cell in V8 which holds an object value and which is updated by the garbage collector whenever the object is moved. A new storage cell can be created using the constructor or `Nan::PersistentBase::Reset()`. Existing handles can be disposed using an argument-less `Nan::PersistentBase::Reset()`. + +Definition: + +_(note: this is implemented as `Nan::PersistentBase` for older versions of V8 and the native `v8::PersistentBase` is used for newer versions of V8)_ + +```c++ +template class PersistentBase { + public: + /** + * If non-empty, destroy the underlying storage cell + */ + void Reset(); + + /** + * If non-empty, destroy the underlying storage cell and create a new one with + * the contents of another if it is also non-empty + */ + template void Reset(const v8::Local &other); + + /** + * If non-empty, destroy the underlying storage cell and create a new one with + * the contents of another if it is also non-empty + */ + template void Reset(const PersistentBase &other); + + /** Returns true if the handle is empty. */ + bool IsEmpty() const; + + /** + * If non-empty, destroy the underlying storage cell + * IsEmpty() will return true after this call. + */ + void Empty(); + + template bool operator==(const PersistentBase &that); + + template bool operator==(const v8::Local &that); + + template bool operator!=(const PersistentBase &that); + + template bool operator!=(const v8::Local &that); + + /** + * Install a finalization callback on this object. + * NOTE: There is no guarantee as to *when* or even *if* the callback is + * invoked. The invocation is performed solely on a best effort basis. + * As always, GC-based finalization should *not* be relied upon for any + * critical form of resource management! At the moment you can either + * specify a parameter for the callback or the location of two internal + * fields in the dying object. + */ + template + void SetWeak(P *parameter, + typename WeakCallbackInfo

::Callback callback, + WeakCallbackType type); + + void ClearWeak(); + + /** + * Marks the reference to this object independent. Garbage collector is free + * to ignore any object groups containing this object. Weak callback for an + * independent handle should not assume that it will be preceded by a global + * GC prologue callback or followed by a global GC epilogue callback. + */ + void MarkIndependent() const; + + bool IsIndependent() const; + + /** Checks if the handle holds the only reference to an object. */ + bool IsNearDeath() const; + + /** Returns true if the handle's reference is weak. */ + bool IsWeak() const +}; +``` + +See the V8 documentation for [`PersistentBase`](https://v8docs.nodesource.com/node-8.11/d4/dca/classv8_1_1_persistent_base.html) for further information. + +**Tip:** To get a `v8::Local` reference to the original object back from a `PersistentBase` or `Persistent` object: + +```c++ +v8::Local object = Nan::New(persistent); +``` + + +### Nan::NonCopyablePersistentTraits & v8::NonCopyablePersistentTraits + +Default traits for `Nan::Persistent`. This class does not allow use of the a copy constructor or assignment operator. At present `kResetInDestructor` is not set, but that will change in a future version. + +Definition: + +_(note: this is implemented as `Nan::NonCopyablePersistentTraits` for older versions of V8 and the native `v8::NonCopyablePersistentTraits` is used for newer versions of V8)_ + +```c++ +template class NonCopyablePersistentTraits { + public: + typedef Persistent > NonCopyablePersistent; + + static const bool kResetInDestructor = false; + + template + static void Copy(const Persistent &source, + NonCopyablePersistent *dest); + + template static void Uncompilable(); +}; +``` + +See the V8 documentation for [`NonCopyablePersistentTraits`](https://v8docs.nodesource.com/node-8.11/de/d73/classv8_1_1_non_copyable_persistent_traits.html) for further information. + + +### Nan::CopyablePersistentTraits & v8::CopyablePersistentTraits + +A helper class of traits to allow copying and assignment of `Persistent`. This will clone the contents of storage cell, but not any of the flags, etc.. + +Definition: + +_(note: this is implemented as `Nan::CopyablePersistentTraits` for older versions of V8 and the native `v8::NonCopyablePersistentTraits` is used for newer versions of V8)_ + +```c++ +template +class CopyablePersistentTraits { + public: + typedef Persistent > CopyablePersistent; + + static const bool kResetInDestructor = true; + + template + static void Copy(const Persistent &source, + CopyablePersistent *dest); +}; +``` + +See the V8 documentation for [`CopyablePersistentTraits`](https://v8docs.nodesource.com/node-8.11/da/d5c/structv8_1_1_copyable_persistent_traits.html) for further information. + + +### Nan::Persistent + +A type of `PersistentBase` which allows copy and assignment. Copy, assignment and destructor behavior is controlled by the traits class `M`. + +Definition: + +```c++ +template > +class Persistent; + +template class Persistent : public PersistentBase { + public: + /** + * A Persistent with no storage cell. + */ + Persistent(); + + /** + * Construct a Persistent from a v8::Local. When the v8::Local is non-empty, a + * new storage cell is created pointing to the same object, and no flags are + * set. + */ + template Persistent(v8::Local that); + + /** + * Construct a Persistent from a Persistent. When the Persistent is non-empty, + * a new storage cell is created pointing to the same object, and no flags are + * set. + */ + Persistent(const Persistent &that); + + /** + * The copy constructors and assignment operator create a Persistent exactly + * as the Persistent constructor, but the Copy function from the traits class + * is called, allowing the setting of flags based on the copied Persistent. + */ + Persistent &operator=(const Persistent &that); + + template + Persistent &operator=(const Persistent &that); + + /** + * The destructor will dispose the Persistent based on the kResetInDestructor + * flags in the traits class. Since not calling dispose can result in a + * memory leak, it is recommended to always set this flag. + */ + ~Persistent(); +}; +``` + +See the V8 documentation for [`Persistent`](https://v8docs.nodesource.com/node-8.11/d2/d78/classv8_1_1_persistent.html) for further information. + + +### Nan::Global + +A type of `PersistentBase` which has move semantics. + +```c++ +template class Global : public PersistentBase { + public: + /** + * A Global with no storage cell. + */ + Global(); + + /** + * Construct a Global from a v8::Local. When the v8::Local is non-empty, a new + * storage cell is created pointing to the same object, and no flags are set. + */ + template Global(v8::Local that); + /** + * Construct a Global from a PersistentBase. When the Persistent is non-empty, + * a new storage cell is created pointing to the same object, and no flags are + * set. + */ + template Global(const PersistentBase &that); + + /** + * Pass allows returning globals from functions, etc. + */ + Global Pass(); +}; +``` + +See the V8 documentation for [`Global`](https://v8docs.nodesource.com/node-8.11/d5/d40/classv8_1_1_global.html) for further information. + + +### Nan::WeakCallbackInfo + +`Nan::WeakCallbackInfo` is used as an argument when setting a persistent reference as weak. You may need to free any external resources attached to the object. It is a mirror of `v8:WeakCallbackInfo` as found in newer versions of V8. + +Definition: + +```c++ +template class WeakCallbackInfo { + public: + typedef void (*Callback)(const WeakCallbackInfo& data); + + v8::Isolate *GetIsolate() const; + + /** + * Get the parameter that was associated with the weak handle. + */ + T *GetParameter() const; + + /** + * Get pointer from internal field, index can be 0 or 1. + */ + void *GetInternalField(int index) const; +}; +``` + +Example usage: + +```c++ +void weakCallback(const WeakCallbackInfo &data) { + int *parameter = data.GetParameter(); + delete parameter; +} + +Persistent obj; +int *data = new int(0); +obj.SetWeak(data, callback, WeakCallbackType::kParameter); +``` + +See the V8 documentation for [`WeakCallbackInfo`](https://v8docs.nodesource.com/node-8.11/d8/d06/classv8_1_1_weak_callback_info.html) for further information. + + +### Nan::WeakCallbackType + +Represents the type of a weak callback. +A weak callback of type `kParameter` makes the supplied parameter to `Nan::PersistentBase::SetWeak` available through `WeakCallbackInfo::GetParameter`. +A weak callback of type `kInternalFields` uses up to two internal fields at indices 0 and 1 on the `Nan::PersistentBase` being made weak. +Note that only `v8::Object`s and derivatives can have internal fields. + +Definition: + +```c++ +enum class WeakCallbackType { kParameter, kInternalFields }; +``` diff --git a/express-server/node_modules/nan/doc/scopes.md b/express-server/node_modules/nan/doc/scopes.md new file mode 100644 index 00000000..27ab8630 --- /dev/null +++ b/express-server/node_modules/nan/doc/scopes.md @@ -0,0 +1,73 @@ +## Scopes + +A _local handle_ is a pointer to an object. All V8 objects are accessed using handles, they are necessary because of the way the V8 garbage collector works. + +A handle scope can be thought of as a container for any number of handles. When you've finished with your handles, instead of deleting each one individually you can simply delete their scope. + +The creation of `HandleScope` objects is different across the supported versions of V8. Therefore, NAN provides its own implementations that can be used safely across these. + + - Nan::HandleScope + - Nan::EscapableHandleScope + +Also see the V8 Embedders Guide section on [Handles and Garbage Collection](https://github.com/v8/v8/wiki/Embedder%27s%20Guide#handles-and-garbage-collection). + + +### Nan::HandleScope + +A simple wrapper around [`v8::HandleScope`](https://v8docs.nodesource.com/node-8.11/d3/d95/classv8_1_1_handle_scope.html). + +Definition: + +```c++ +class Nan::HandleScope { + public: + Nan::HandleScope(); + static int NumberOfHandles(); +}; +``` + +Allocate a new `Nan::HandleScope` whenever you are creating new V8 JavaScript objects. Note that an implicit `HandleScope` is created for you on JavaScript-accessible methods so you do not need to insert one yourself. + +Example: + +```c++ +// new object is created, it needs a new scope: +void Pointless() { + Nan::HandleScope scope; + v8::Local obj = Nan::New(); +} + +// JavaScript-accessible method already has a HandleScope +NAN_METHOD(Pointless2) { + v8::Local obj = Nan::New(); +} +``` + + +### Nan::EscapableHandleScope + +Similar to [`Nan::HandleScope`](#api_nan_handle_scope) but should be used in cases where a function needs to return a V8 JavaScript type that has been created within it. + +Definition: + +```c++ +class Nan::EscapableHandleScope { + public: + Nan::EscapableHandleScope(); + static int NumberOfHandles(); + template v8::Local Escape(v8::Local value); +} +``` + +Use `Escape(value)` to return the object. + +Example: + +```c++ +v8::Local EmptyObj() { + Nan::EscapableHandleScope scope; + v8::Local obj = Nan::New(); + return scope.Escape(obj); +} +``` + diff --git a/express-server/node_modules/nan/doc/script.md b/express-server/node_modules/nan/doc/script.md new file mode 100644 index 00000000..945398f0 --- /dev/null +++ b/express-server/node_modules/nan/doc/script.md @@ -0,0 +1,38 @@ +## Script + +NAN provides a `v8::Script` helpers as the API has changed over the supported versions of V8. + + - Nan::CompileScript() + - Nan::RunScript() + + + +### Nan::CompileScript() + +A wrapper around [`v8::ScriptCompiler::Compile()`](https://v8docs.nodesource.com/node-8.11/da/da5/classv8_1_1_script_compiler.html#a93f5072a0db55d881b969e9fc98e564b). + +Note that `Nan::BoundScript` is an alias for `v8::Script`. + +Signature: + +```c++ +Nan::MaybeLocal Nan::CompileScript( + v8::Local s, + const v8::ScriptOrigin& origin); +Nan::MaybeLocal Nan::CompileScript(v8::Local s); +``` + + + +### Nan::RunScript() + +Calls `script->Run()` or `script->BindToCurrentContext()->Run(Nan::GetCurrentContext())`. + +Note that `Nan::BoundScript` is an alias for `v8::Script` and `Nan::UnboundScript` is an alias for `v8::UnboundScript` where available and `v8::Script` on older versions of V8. + +Signature: + +```c++ +Nan::MaybeLocal Nan::RunScript(v8::Local script) +Nan::MaybeLocal Nan::RunScript(v8::Local script) +``` diff --git a/express-server/node_modules/nan/doc/string_bytes.md b/express-server/node_modules/nan/doc/string_bytes.md new file mode 100644 index 00000000..7c1bd325 --- /dev/null +++ b/express-server/node_modules/nan/doc/string_bytes.md @@ -0,0 +1,62 @@ +## Strings & Bytes + +Miscellaneous string & byte encoding and decoding functionality provided for compatibility across supported versions of V8 and Node. Implemented by NAN to ensure that all encoding types are supported, even for older versions of Node where they are missing. + + - Nan::Encoding + - Nan::Encode() + - Nan::DecodeBytes() + - Nan::DecodeWrite() + + + +### Nan::Encoding + +An enum representing the supported encoding types. A copy of `node::encoding` that is consistent across versions of Node. + +Definition: + +```c++ +enum Nan::Encoding { ASCII, UTF8, BASE64, UCS2, BINARY, HEX, BUFFER } +``` + + + +### Nan::Encode() + +A wrapper around `node::Encode()` that provides a consistent implementation across supported versions of Node. + +Signature: + +```c++ +v8::Local Nan::Encode(const void *buf, + size_t len, + enum Nan::Encoding encoding = BINARY); +``` + + + +### Nan::DecodeBytes() + +A wrapper around `node::DecodeBytes()` that provides a consistent implementation across supported versions of Node. + +Signature: + +```c++ +ssize_t Nan::DecodeBytes(v8::Local val, + enum Nan::Encoding encoding = BINARY); +``` + + + +### Nan::DecodeWrite() + +A wrapper around `node::DecodeWrite()` that provides a consistent implementation across supported versions of Node. + +Signature: + +```c++ +ssize_t Nan::DecodeWrite(char *buf, + size_t len, + v8::Local val, + enum Nan::Encoding encoding = BINARY); +``` diff --git a/express-server/node_modules/nan/doc/v8_internals.md b/express-server/node_modules/nan/doc/v8_internals.md new file mode 100644 index 00000000..88bd2deb --- /dev/null +++ b/express-server/node_modules/nan/doc/v8_internals.md @@ -0,0 +1,199 @@ +## V8 internals + +The hooks to access V8 internals—including GC and statistics—are different across the supported versions of V8, therefore NAN provides its own hooks that call the appropriate V8 methods. + + - NAN_GC_CALLBACK() + - Nan::AddGCEpilogueCallback() + - Nan::RemoveGCEpilogueCallback() + - Nan::AddGCPrologueCallback() + - Nan::RemoveGCPrologueCallback() + - Nan::GetHeapStatistics() + - Nan::SetCounterFunction() + - Nan::SetCreateHistogramFunction() + - Nan::SetAddHistogramSampleFunction() + - Nan::IdleNotification() + - Nan::LowMemoryNotification() + - Nan::ContextDisposedNotification() + - Nan::GetInternalFieldPointer() + - Nan::SetInternalFieldPointer() + - Nan::AdjustExternalMemory() + + + +### NAN_GC_CALLBACK(callbackname) + +Use `NAN_GC_CALLBACK` to declare your callbacks for `Nan::AddGCPrologueCallback()` and `Nan::AddGCEpilogueCallback()`. Your new method receives the arguments `v8::GCType type` and `v8::GCCallbackFlags flags`. + +```c++ +static Nan::Persistent callback; + +NAN_GC_CALLBACK(gcPrologueCallback) { + v8::Local argv[] = { Nan::New("prologue").ToLocalChecked() }; + Nan::MakeCallback(Nan::GetCurrentContext()->Global(), Nan::New(callback), 1, argv); +} + +NAN_METHOD(Hook) { + callback.Reset(To(args[0]).ToLocalChecked()); + Nan::AddGCPrologueCallback(gcPrologueCallback); + info.GetReturnValue().Set(info.Holder()); +} +``` + + +### Nan::AddGCEpilogueCallback() + +Signature: + +```c++ +void Nan::AddGCEpilogueCallback(v8::Isolate::GCEpilogueCallback callback, v8::GCType gc_type_filter = v8::kGCTypeAll) +``` + +Calls V8's [`AddGCEpilogueCallback()`](https://v8docs.nodesource.com/node-8.11/d5/dda/classv8_1_1_isolate.html#a580f976e4290cead62c2fc4dd396be3e). + + +### Nan::RemoveGCEpilogueCallback() + +Signature: + +```c++ +void Nan::RemoveGCEpilogueCallback(v8::Isolate::GCEpilogueCallback callback) +``` + +Calls V8's [`RemoveGCEpilogueCallback()`](https://v8docs.nodesource.com/node-8.11/d5/dda/classv8_1_1_isolate.html#adca9294555a3908e9f23c7bb0f0f284c). + + +### Nan::AddGCPrologueCallback() + +Signature: + +```c++ +void Nan::AddGCPrologueCallback(v8::Isolate::GCPrologueCallback, v8::GCType gc_type_filter callback) +``` + +Calls V8's [`AddGCPrologueCallback()`](https://v8docs.nodesource.com/node-8.11/d5/dda/classv8_1_1_isolate.html#a6dbef303603ebdb03da6998794ea05b8). + + +### Nan::RemoveGCPrologueCallback() + +Signature: + +```c++ +void Nan::RemoveGCPrologueCallback(v8::Isolate::GCPrologueCallback callback) +``` + +Calls V8's [`RemoveGCPrologueCallback()`](https://v8docs.nodesource.com/node-8.11/d5/dda/classv8_1_1_isolate.html#a5f72c7cda21415ce062bbe5c58abe09e). + + +### Nan::GetHeapStatistics() + +Signature: + +```c++ +void Nan::GetHeapStatistics(v8::HeapStatistics *heap_statistics) +``` + +Calls V8's [`GetHeapStatistics()`](https://v8docs.nodesource.com/node-8.11/d5/dda/classv8_1_1_isolate.html#a5593ac74687b713095c38987e5950b34). + + +### Nan::SetCounterFunction() + +Signature: + +```c++ +void Nan::SetCounterFunction(v8::CounterLookupCallback cb) +``` + +Calls V8's [`SetCounterFunction()`](https://v8docs.nodesource.com/node-8.11/d5/dda/classv8_1_1_isolate.html#a045d7754e62fa0ec72ae6c259b29af94). + + +### Nan::SetCreateHistogramFunction() + +Signature: + +```c++ +void Nan::SetCreateHistogramFunction(v8::CreateHistogramCallback cb) +``` + +Calls V8's [`SetCreateHistogramFunction()`](https://v8docs.nodesource.com/node-8.11/d5/dda/classv8_1_1_isolate.html#a542d67e85089cb3f92aadf032f99e732). + + +### Nan::SetAddHistogramSampleFunction() + +Signature: + +```c++ +void Nan::SetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb) +``` + +Calls V8's [`SetAddHistogramSampleFunction()`](https://v8docs.nodesource.com/node-8.11/d5/dda/classv8_1_1_isolate.html#aeb420b690bc2c216882d6fdd00ddd3ea). + + +### Nan::IdleNotification() + +Signature: + +```c++ +bool Nan::IdleNotification(int idle_time_in_ms) +``` + +Calls V8's [`IdleNotification()` or `IdleNotificationDeadline()`](https://v8docs.nodesource.com/node-8.11/d5/dda/classv8_1_1_isolate.html#ad6a2a02657f5425ad460060652a5a118) depending on V8 version. + + +### Nan::LowMemoryNotification() + +Signature: + +```c++ +void Nan::LowMemoryNotification() +``` + +Calls V8's [`LowMemoryNotification()`](https://v8docs.nodesource.com/node-8.11/d5/dda/classv8_1_1_isolate.html#a24647f61d6b41f69668094bdcd6ea91f). + + +### Nan::ContextDisposedNotification() + +Signature: + +```c++ +void Nan::ContextDisposedNotification() +``` + +Calls V8's [`ContextDisposedNotification()`](https://v8docs.nodesource.com/node-8.11/d5/dda/classv8_1_1_isolate.html#ad7f5dc559866343fe6cd8db1f134d48b). + + +### Nan::GetInternalFieldPointer() + +Gets a pointer to the internal field with at `index` from a V8 `Object` handle. + +Signature: + +```c++ +void* Nan::GetInternalFieldPointer(v8::Local object, int index) +``` + +Calls the Object's [`GetAlignedPointerFromInternalField()` or `GetPointerFromInternalField()`](https://v8docs.nodesource.com/node-8.11/db/d85/classv8_1_1_object.html#a580ea84afb26c005d6762eeb9e3c308f) depending on the version of V8. + + +### Nan::SetInternalFieldPointer() + +Sets the value of the internal field at `index` on a V8 `Object` handle. + +Signature: + +```c++ +void Nan::SetInternalFieldPointer(v8::Local object, int index, void* value) +``` + +Calls the Object's [`SetAlignedPointerInInternalField()` or `SetPointerInInternalField()`](https://v8docs.nodesource.com/node-8.11/db/d85/classv8_1_1_object.html#ab3c57184263cf29963ef0017bec82281) depending on the version of V8. + + +### Nan::AdjustExternalMemory() + +Signature: + +```c++ +int Nan::AdjustExternalMemory(int bytesChange) +``` + +Calls V8's [`AdjustAmountOfExternalAllocatedMemory()`](https://v8docs.nodesource.com/node-8.11/d5/dda/classv8_1_1_isolate.html#ae1a59cac60409d3922582c4af675473e). + diff --git a/express-server/node_modules/nan/doc/v8_misc.md b/express-server/node_modules/nan/doc/v8_misc.md new file mode 100644 index 00000000..8e2db20d --- /dev/null +++ b/express-server/node_modules/nan/doc/v8_misc.md @@ -0,0 +1,85 @@ +## Miscellaneous V8 Helpers + + - Nan::Utf8String + - Nan::GetCurrentContext() + - Nan::SetIsolateData() + - Nan::GetIsolateData() + - Nan::TypedArrayContents + + + +### Nan::Utf8String + +Converts an object to a UTF-8-encoded character array. If conversion to a string fails (e.g. due to an exception in the toString() method of the object) then the length() method returns 0 and the * operator returns NULL. The underlying memory used for this object is managed by the object. + +An implementation of [`v8::String::Utf8Value`](https://v8docs.nodesource.com/node-8.11/d4/d1b/classv8_1_1_string_1_1_utf8_value.html) that is consistent across all supported versions of V8. + +Definition: + +```c++ +class Nan::Utf8String { + public: + Nan::Utf8String(v8::Local from); + + int length() const; + + char* operator*(); + const char* operator*() const; +}; +``` + + +### Nan::GetCurrentContext() + +A call to [`v8::Isolate::GetCurrent()->GetCurrentContext()`](https://v8docs.nodesource.com/node-8.11/d5/dda/classv8_1_1_isolate.html#a81c7a1ed7001ae2a65e89107f75fd053) that works across all supported versions of V8. + +Signature: + +```c++ +v8::Local Nan::GetCurrentContext() +``` + + +### Nan::SetIsolateData() + +A helper to provide a consistent API to [`v8::Isolate#SetData()`](https://v8docs.nodesource.com/node-8.11/d5/dda/classv8_1_1_isolate.html#a7acadfe7965997e9c386a05f098fbe36). + +Signature: + +```c++ +void Nan::SetIsolateData(v8::Isolate *isolate, T *data) +``` + + + +### Nan::GetIsolateData() + +A helper to provide a consistent API to [`v8::Isolate#GetData()`](https://v8docs.nodesource.com/node-8.11/d5/dda/classv8_1_1_isolate.html#aabd223436bc1100a787dadaa024c6257). + +Signature: + +```c++ +T *Nan::GetIsolateData(v8::Isolate *isolate) +``` + + +### Nan::TypedArrayContents + +A helper class for accessing the contents of an ArrayBufferView (aka a typedarray) from C++. If the input array is not a valid typedarray, then the data pointer of TypedArrayContents will default to `NULL` and the length will be 0. If the data pointer is not compatible with the alignment requirements of type, an assertion error will fail. + +Note that you must store a reference to the `array` object while you are accessing its contents. + +Definition: + +```c++ +template +class Nan::TypedArrayContents { + public: + TypedArrayContents(v8::Local array); + + size_t length() const; + + T* const operator*(); + const T* const operator*() const; +}; +``` diff --git a/express-server/node_modules/nan/include_dirs.js b/express-server/node_modules/nan/include_dirs.js new file mode 100644 index 00000000..4f1dfb41 --- /dev/null +++ b/express-server/node_modules/nan/include_dirs.js @@ -0,0 +1 @@ +console.log(require('path').relative('.', __dirname)); diff --git a/express-server/node_modules/nan/nan.h b/express-server/node_modules/nan/nan.h new file mode 100644 index 00000000..e3419a37 --- /dev/null +++ b/express-server/node_modules/nan/nan.h @@ -0,0 +1,2810 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors: + * - Rod Vagg + * - Benjamin Byholm + * - Trevor Norris + * - Nathan Rajlich + * - Brett Lawson + * - Ben Noordhuis + * - David Siegel + * - Michael Ira Krufky + * + * MIT License + * + * Version 2.12.0: current Node 11.4.0, Node 12: 0.12.18, Node 10: 0.10.48, iojs: 3.3.1 + * + * See https://github.com/nodejs/nan for the latest update to this file + **********************************************************************************/ + +#ifndef NAN_H_ +#define NAN_H_ + +#include + +#define NODE_0_10_MODULE_VERSION 11 +#define NODE_0_12_MODULE_VERSION 14 +#define ATOM_0_21_MODULE_VERSION 41 +#define IOJS_1_0_MODULE_VERSION 42 +#define IOJS_1_1_MODULE_VERSION 43 +#define IOJS_2_0_MODULE_VERSION 44 +#define IOJS_3_0_MODULE_VERSION 45 +#define NODE_4_0_MODULE_VERSION 46 +#define NODE_5_0_MODULE_VERSION 47 +#define NODE_6_0_MODULE_VERSION 48 +#define NODE_7_0_MODULE_VERSION 51 +#define NODE_8_0_MODULE_VERSION 57 +#define NODE_9_0_MODULE_VERSION 59 +#define NODE_10_0_MODULE_VERSION 64 +#define NODE_11_0_MODULE_VERSION 67 + +#ifdef _MSC_VER +# define NAN_HAS_CPLUSPLUS_11 (_MSC_VER >= 1800) +#else +# define NAN_HAS_CPLUSPLUS_11 (__cplusplus >= 201103L) +#endif + +#if NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION && !NAN_HAS_CPLUSPLUS_11 +# error This version of node/NAN/v8 requires a C++11 compiler +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(_MSC_VER) +# pragma warning( push ) +# pragma warning( disable : 4530 ) +# include +# include +# include +# pragma warning( pop ) +#else +# include +# include +# include +#endif + +// uv helpers +#ifdef UV_VERSION_MAJOR +# ifndef UV_VERSION_PATCH +# define UV_VERSION_PATCH 0 +# endif +# define NAUV_UVVERSION ((UV_VERSION_MAJOR << 16) | \ + (UV_VERSION_MINOR << 8) | \ + (UV_VERSION_PATCH)) +#else +# define NAUV_UVVERSION 0x000b00 +#endif + +#if NAUV_UVVERSION < 0x000b0b +# ifdef WIN32 +# include +# else +# include +# endif +#endif + +namespace Nan { + +#define NAN_CONCAT(a, b) NAN_CONCAT_HELPER(a, b) +#define NAN_CONCAT_HELPER(a, b) a##b + +#define NAN_INLINE inline // TODO(bnoordhuis) Remove in v3.0.0. + +#if defined(__GNUC__) && \ + !(defined(V8_DISABLE_DEPRECATIONS) && V8_DISABLE_DEPRECATIONS) +# define NAN_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) && \ + !(defined(V8_DISABLE_DEPRECATIONS) && V8_DISABLE_DEPRECATIONS) +# define NAN_DEPRECATED __declspec(deprecated) +#else +# define NAN_DEPRECATED +#endif + +#if NAN_HAS_CPLUSPLUS_11 +# define NAN_DISALLOW_ASSIGN(CLASS) void operator=(const CLASS&) = delete; +# define NAN_DISALLOW_COPY(CLASS) CLASS(const CLASS&) = delete; +# define NAN_DISALLOW_MOVE(CLASS) \ + CLASS(CLASS&&) = delete; /* NOLINT(build/c++11) */ \ + void operator=(CLASS&&) = delete; +#else +# define NAN_DISALLOW_ASSIGN(CLASS) void operator=(const CLASS&); +# define NAN_DISALLOW_COPY(CLASS) CLASS(const CLASS&); +# define NAN_DISALLOW_MOVE(CLASS) +#endif + +#define NAN_DISALLOW_ASSIGN_COPY(CLASS) \ + NAN_DISALLOW_ASSIGN(CLASS) \ + NAN_DISALLOW_COPY(CLASS) + +#define NAN_DISALLOW_ASSIGN_MOVE(CLASS) \ + NAN_DISALLOW_ASSIGN(CLASS) \ + NAN_DISALLOW_MOVE(CLASS) + +#define NAN_DISALLOW_COPY_MOVE(CLASS) \ + NAN_DISALLOW_COPY(CLASS) \ + NAN_DISALLOW_MOVE(CLASS) + +#define NAN_DISALLOW_ASSIGN_COPY_MOVE(CLASS) \ + NAN_DISALLOW_ASSIGN(CLASS) \ + NAN_DISALLOW_COPY(CLASS) \ + NAN_DISALLOW_MOVE(CLASS) + +#define TYPE_CHECK(T, S) \ + while (false) { \ + *(static_cast(0)) = static_cast(0); \ + } + +//=== RegistrationFunction ===================================================== + +#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + typedef v8::Handle ADDON_REGISTER_FUNCTION_ARGS_TYPE; +#else + typedef v8::Local ADDON_REGISTER_FUNCTION_ARGS_TYPE; +#endif + +#define NAN_MODULE_INIT(name) \ + void name(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) + +#if NODE_MAJOR_VERSION >= 10 || \ + NODE_MAJOR_VERSION == 9 && NODE_MINOR_VERSION >= 3 +#define NAN_MODULE_WORKER_ENABLED(module_name, registration) \ + extern "C" NODE_MODULE_EXPORT void \ + NAN_CONCAT(node_register_module_v, NODE_MODULE_VERSION)( \ + v8::Local exports, v8::Local module, \ + v8::Local context) \ + { \ + registration(exports); \ + } +#else +#define NAN_MODULE_WORKER_ENABLED(module_name, registration) \ + NODE_MODULE(module_name, registration) +#endif + +//=== CallbackInfo ============================================================= + +#include "nan_callbacks.h" // NOLINT(build/include) + +//============================================================================== + +#if (NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION) +typedef v8::Script UnboundScript; +typedef v8::Script BoundScript; +#else +typedef v8::UnboundScript UnboundScript; +typedef v8::Script BoundScript; +#endif + +#if (NODE_MODULE_VERSION < ATOM_0_21_MODULE_VERSION) +typedef v8::String::ExternalAsciiStringResource + ExternalOneByteStringResource; +#else +typedef v8::String::ExternalOneByteStringResource + ExternalOneByteStringResource; +#endif + +#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION) +template +class NonCopyablePersistentTraits : + public v8::NonCopyablePersistentTraits {}; +template +class CopyablePersistentTraits : + public v8::CopyablePersistentTraits {}; + +template +class PersistentBase : + public v8::PersistentBase {}; + +template > +class Persistent; +#else +template class NonCopyablePersistentTraits; +template class PersistentBase; +template class WeakCallbackData; +template > +class Persistent; +#endif // NODE_MODULE_VERSION + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +# include "nan_maybe_43_inl.h" // NOLINT(build/include) +#else +# include "nan_maybe_pre_43_inl.h" // NOLINT(build/include) +#endif + +#include "nan_converters.h" // NOLINT(build/include) +#include "nan_new.h" // NOLINT(build/include) + +#if NAUV_UVVERSION < 0x000b17 +#define NAUV_WORK_CB(func) \ + void func(uv_async_t *async, int) +#else +#define NAUV_WORK_CB(func) \ + void func(uv_async_t *async) +#endif + +#if NAUV_UVVERSION >= 0x000b0b + +typedef uv_key_t nauv_key_t; + +inline int nauv_key_create(nauv_key_t *key) { + return uv_key_create(key); +} + +inline void nauv_key_delete(nauv_key_t *key) { + uv_key_delete(key); +} + +inline void* nauv_key_get(nauv_key_t *key) { + return uv_key_get(key); +} + +inline void nauv_key_set(nauv_key_t *key, void *value) { + uv_key_set(key, value); +} + +#else + +/* Implement thread local storage for older versions of libuv. + * This is essentially a backport of libuv commit 5d2434bf + * written by Ben Noordhuis, adjusted for names and inline. + */ + +#ifndef WIN32 + +typedef pthread_key_t nauv_key_t; + +inline int nauv_key_create(nauv_key_t* key) { + return -pthread_key_create(key, NULL); +} + +inline void nauv_key_delete(nauv_key_t* key) { + if (pthread_key_delete(*key)) + abort(); +} + +inline void* nauv_key_get(nauv_key_t* key) { + return pthread_getspecific(*key); +} + +inline void nauv_key_set(nauv_key_t* key, void* value) { + if (pthread_setspecific(*key, value)) + abort(); +} + +#else + +typedef struct { + DWORD tls_index; +} nauv_key_t; + +inline int nauv_key_create(nauv_key_t* key) { + key->tls_index = TlsAlloc(); + if (key->tls_index == TLS_OUT_OF_INDEXES) + return UV_ENOMEM; + return 0; +} + +inline void nauv_key_delete(nauv_key_t* key) { + if (TlsFree(key->tls_index) == FALSE) + abort(); + key->tls_index = TLS_OUT_OF_INDEXES; +} + +inline void* nauv_key_get(nauv_key_t* key) { + void* value = TlsGetValue(key->tls_index); + if (value == NULL) + if (GetLastError() != ERROR_SUCCESS) + abort(); + return value; +} + +inline void nauv_key_set(nauv_key_t* key, void* value) { + if (TlsSetValue(key->tls_index, value) == FALSE) + abort(); +} + +#endif +#endif + +#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION +template +v8::Local New(v8::Handle); +#endif + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + typedef v8::WeakCallbackType WeakCallbackType; +#else +struct WeakCallbackType { + enum E {kParameter, kInternalFields}; + E type; + WeakCallbackType(E other) : type(other) {} // NOLINT(runtime/explicit) + inline bool operator==(E other) { return other == this->type; } + inline bool operator!=(E other) { return !operator==(other); } +}; +#endif + +template class WeakCallbackInfo; + +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION +# include "nan_persistent_12_inl.h" // NOLINT(build/include) +#else +# include "nan_persistent_pre_12_inl.h" // NOLINT(build/include) +#endif + +namespace imp { + static const size_t kMaxLength = 0x3fffffff; + // v8::String::REPLACE_INVALID_UTF8 was introduced + // in node.js v0.10.29 and v0.8.27. +#if NODE_MAJOR_VERSION > 0 || \ + NODE_MINOR_VERSION > 10 || \ + NODE_MINOR_VERSION == 10 && NODE_PATCH_VERSION >= 29 || \ + NODE_MINOR_VERSION == 8 && NODE_PATCH_VERSION >= 27 + static const unsigned kReplaceInvalidUtf8 = v8::String::REPLACE_INVALID_UTF8; +#else + static const unsigned kReplaceInvalidUtf8 = 0; +#endif +} // end of namespace imp + +//=== HandleScope ============================================================== + +class HandleScope { + v8::HandleScope scope; + + public: +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + inline HandleScope() : scope(v8::Isolate::GetCurrent()) {} + inline static int NumberOfHandles() { + return v8::HandleScope::NumberOfHandles(v8::Isolate::GetCurrent()); + } +#else + inline HandleScope() : scope() {} + inline static int NumberOfHandles() { + return v8::HandleScope::NumberOfHandles(); + } +#endif + + private: + // Make it hard to create heap-allocated or illegal handle scopes by + // disallowing certain operations. + HandleScope(const HandleScope &); + void operator=(const HandleScope &); + void *operator new(size_t size); + void operator delete(void *, size_t) { + abort(); + } +}; + +class EscapableHandleScope { + public: +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + inline EscapableHandleScope() : scope(v8::Isolate::GetCurrent()) {} + + inline static int NumberOfHandles() { + return v8::EscapableHandleScope::NumberOfHandles(v8::Isolate::GetCurrent()); + } + + template + inline v8::Local Escape(v8::Local value) { + return scope.Escape(value); + } + + private: + v8::EscapableHandleScope scope; +#else + inline EscapableHandleScope() : scope() {} + + inline static int NumberOfHandles() { + return v8::HandleScope::NumberOfHandles(); + } + + template + inline v8::Local Escape(v8::Local value) { + return scope.Close(value); + } + + private: + v8::HandleScope scope; +#endif + + private: + // Make it hard to create heap-allocated or illegal handle scopes by + // disallowing certain operations. + EscapableHandleScope(const EscapableHandleScope &); + void operator=(const EscapableHandleScope &); + void *operator new(size_t size); + void operator delete(void *, size_t) { + abort(); + } +}; + +//=== TryCatch ================================================================= + +class TryCatch { + v8::TryCatch try_catch_; + friend void FatalException(const TryCatch&); + + public: +#if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION + TryCatch() : try_catch_(v8::Isolate::GetCurrent()) {} +#endif + + inline bool HasCaught() const { return try_catch_.HasCaught(); } + + inline bool CanContinue() const { return try_catch_.CanContinue(); } + + inline v8::Local ReThrow() { +#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + return New(try_catch_.ReThrow()); +#else + return try_catch_.ReThrow(); +#endif + } + + inline v8::Local Exception() const { + return try_catch_.Exception(); + } + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + inline v8::MaybeLocal StackTrace() const { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(try_catch_.StackTrace(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); + } +#else + inline MaybeLocal StackTrace() const { + return try_catch_.StackTrace(); + } +#endif + + inline v8::Local Message() const { + return try_catch_.Message(); + } + + inline void Reset() { try_catch_.Reset(); } + + inline void SetVerbose(bool value) { try_catch_.SetVerbose(value); } + + inline void SetCaptureMessage(bool value) { + try_catch_.SetCaptureMessage(value); + } +}; + +v8::Local MakeCallback(v8::Local target, + v8::Local func, + int argc, + v8::Local* argv); +v8::Local MakeCallback(v8::Local target, + v8::Local symbol, + int argc, + v8::Local* argv); +v8::Local MakeCallback(v8::Local target, + const char* method, + int argc, + v8::Local* argv); + +// === AsyncResource =========================================================== + +class AsyncResource { + public: + AsyncResource( + v8::Local name + , v8::Local resource = New()) { +#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + + if (resource.IsEmpty()) { + resource = New(); + } + + context = node::EmitAsyncInit(isolate, resource, name); +#endif + } + + AsyncResource( + const char* name + , v8::Local resource = New()) { +#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + + if (resource.IsEmpty()) { + resource = New(); + } + + v8::Local name_string = + New(name).ToLocalChecked(); + context = node::EmitAsyncInit(isolate, resource, name_string); +#endif + } + + ~AsyncResource() { +#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + node::EmitAsyncDestroy(isolate, context); +#endif + } + + inline MaybeLocal runInAsyncScope( + v8::Local target + , v8::Local func + , int argc + , v8::Local* argv) { +#if NODE_MODULE_VERSION < NODE_9_0_MODULE_VERSION + return MakeCallback(target, func, argc, argv); +#else + return node::MakeCallback( + v8::Isolate::GetCurrent(), target, func, argc, argv, context); +#endif + } + + inline MaybeLocal runInAsyncScope( + v8::Local target + , v8::Local symbol + , int argc + , v8::Local* argv) { +#if NODE_MODULE_VERSION < NODE_9_0_MODULE_VERSION + return MakeCallback(target, symbol, argc, argv); +#else + return node::MakeCallback( + v8::Isolate::GetCurrent(), target, symbol, argc, argv, context); +#endif + } + + inline MaybeLocal runInAsyncScope( + v8::Local target + , const char* method + , int argc + , v8::Local* argv) { +#if NODE_MODULE_VERSION < NODE_9_0_MODULE_VERSION + return MakeCallback(target, method, argc, argv); +#else + return node::MakeCallback( + v8::Isolate::GetCurrent(), target, method, argc, argv, context); +#endif + } + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(AsyncResource) +#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + node::async_context context; +#endif +}; + +inline uv_loop_t* GetCurrentEventLoop() { +#if NODE_MAJOR_VERSION >= 10 || \ + NODE_MAJOR_VERSION == 9 && NODE_MINOR_VERSION >= 3 || \ + NODE_MAJOR_VERSION == 8 && NODE_MINOR_VERSION >= 10 + return node::GetCurrentEventLoop(v8::Isolate::GetCurrent()); +#else + return uv_default_loop(); +#endif +} + +//============ ================================================================= + +/* node 0.12 */ +#if NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION + inline + void SetCounterFunction(v8::CounterLookupCallback cb) { + v8::Isolate::GetCurrent()->SetCounterFunction(cb); + } + + inline + void SetCreateHistogramFunction(v8::CreateHistogramCallback cb) { + v8::Isolate::GetCurrent()->SetCreateHistogramFunction(cb); + } + + inline + void SetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb) { + v8::Isolate::GetCurrent()->SetAddHistogramSampleFunction(cb); + } + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + inline bool IdleNotification(int idle_time_in_ms) { + return v8::Isolate::GetCurrent()->IdleNotificationDeadline( + idle_time_in_ms * 0.001); + } +# else + inline bool IdleNotification(int idle_time_in_ms) { + return v8::Isolate::GetCurrent()->IdleNotification(idle_time_in_ms); + } +#endif + + inline void LowMemoryNotification() { + v8::Isolate::GetCurrent()->LowMemoryNotification(); + } + + inline void ContextDisposedNotification() { + v8::Isolate::GetCurrent()->ContextDisposedNotification(); + } +#else + inline + void SetCounterFunction(v8::CounterLookupCallback cb) { + v8::V8::SetCounterFunction(cb); + } + + inline + void SetCreateHistogramFunction(v8::CreateHistogramCallback cb) { + v8::V8::SetCreateHistogramFunction(cb); + } + + inline + void SetAddHistogramSampleFunction(v8::AddHistogramSampleCallback cb) { + v8::V8::SetAddHistogramSampleFunction(cb); + } + + inline bool IdleNotification(int idle_time_in_ms) { + return v8::V8::IdleNotification(idle_time_in_ms); + } + + inline void LowMemoryNotification() { + v8::V8::LowMemoryNotification(); + } + + inline void ContextDisposedNotification() { + v8::V8::ContextDisposedNotification(); + } +#endif + +#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION) // Node 0.12 + inline v8::Local Undefined() { +# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + EscapableHandleScope scope; + return scope.Escape(New(v8::Undefined(v8::Isolate::GetCurrent()))); +# else + return v8::Undefined(v8::Isolate::GetCurrent()); +# endif + } + + inline v8::Local Null() { +# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + EscapableHandleScope scope; + return scope.Escape(New(v8::Null(v8::Isolate::GetCurrent()))); +# else + return v8::Null(v8::Isolate::GetCurrent()); +# endif + } + + inline v8::Local True() { +# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + EscapableHandleScope scope; + return scope.Escape(New(v8::True(v8::Isolate::GetCurrent()))); +# else + return v8::True(v8::Isolate::GetCurrent()); +# endif + } + + inline v8::Local False() { +# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + EscapableHandleScope scope; + return scope.Escape(New(v8::False(v8::Isolate::GetCurrent()))); +# else + return v8::False(v8::Isolate::GetCurrent()); +# endif + } + + inline v8::Local EmptyString() { + return v8::String::Empty(v8::Isolate::GetCurrent()); + } + + inline int AdjustExternalMemory(int bc) { + return static_cast( + v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(bc)); + } + + inline void SetTemplate( + v8::Local templ + , const char *name + , v8::Local value) { + templ->Set(v8::Isolate::GetCurrent(), name, value); + } + + inline void SetTemplate( + v8::Local templ + , v8::Local name + , v8::Local value + , v8::PropertyAttribute attributes) { + templ->Set(name, value, attributes); + } + + inline v8::Local GetCurrentContext() { + return v8::Isolate::GetCurrent()->GetCurrentContext(); + } + + inline void* GetInternalFieldPointer( + v8::Local object + , int index) { + return object->GetAlignedPointerFromInternalField(index); + } + + inline void SetInternalFieldPointer( + v8::Local object + , int index + , void* value) { + object->SetAlignedPointerInInternalField(index, value); + } + +# define NAN_GC_CALLBACK(name) \ + void name(v8::Isolate *isolate, v8::GCType type, v8::GCCallbackFlags flags) + +#if NODE_MODULE_VERSION <= NODE_4_0_MODULE_VERSION + typedef v8::Isolate::GCEpilogueCallback GCEpilogueCallback; + typedef v8::Isolate::GCPrologueCallback GCPrologueCallback; +#else + typedef v8::Isolate::GCCallback GCEpilogueCallback; + typedef v8::Isolate::GCCallback GCPrologueCallback; +#endif + + inline void AddGCEpilogueCallback( + GCEpilogueCallback callback + , v8::GCType gc_type_filter = v8::kGCTypeAll) { + v8::Isolate::GetCurrent()->AddGCEpilogueCallback(callback, gc_type_filter); + } + + inline void RemoveGCEpilogueCallback( + GCEpilogueCallback callback) { + v8::Isolate::GetCurrent()->RemoveGCEpilogueCallback(callback); + } + + inline void AddGCPrologueCallback( + GCPrologueCallback callback + , v8::GCType gc_type_filter = v8::kGCTypeAll) { + v8::Isolate::GetCurrent()->AddGCPrologueCallback(callback, gc_type_filter); + } + + inline void RemoveGCPrologueCallback( + GCPrologueCallback callback) { + v8::Isolate::GetCurrent()->RemoveGCPrologueCallback(callback); + } + + inline void GetHeapStatistics( + v8::HeapStatistics *heap_statistics) { + v8::Isolate::GetCurrent()->GetHeapStatistics(heap_statistics); + } + +# define X(NAME) \ + inline v8::Local NAME(const char *msg) { \ + EscapableHandleScope scope; \ + return scope.Escape(v8::Exception::NAME(New(msg).ToLocalChecked())); \ + } \ + \ + inline \ + v8::Local NAME(v8::Local msg) { \ + return v8::Exception::NAME(msg); \ + } \ + \ + inline void Throw ## NAME(const char *msg) { \ + HandleScope scope; \ + v8::Isolate::GetCurrent()->ThrowException( \ + v8::Exception::NAME(New(msg).ToLocalChecked())); \ + } \ + \ + inline void Throw ## NAME(v8::Local msg) { \ + HandleScope scope; \ + v8::Isolate::GetCurrent()->ThrowException( \ + v8::Exception::NAME(msg)); \ + } + + X(Error) + X(RangeError) + X(ReferenceError) + X(SyntaxError) + X(TypeError) + +# undef X + + inline void ThrowError(v8::Local error) { + v8::Isolate::GetCurrent()->ThrowException(error); + } + + inline MaybeLocal NewBuffer( + char *data + , size_t length +#if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION + , node::Buffer::FreeCallback callback +#else + , node::smalloc::FreeCallback callback +#endif + , void *hint + ) { + // arbitrary buffer lengths requires + // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION + assert(length <= imp::kMaxLength && "too large buffer"); +#if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION + return node::Buffer::New( + v8::Isolate::GetCurrent(), data, length, callback, hint); +#else + return node::Buffer::New(v8::Isolate::GetCurrent(), data, length, callback, + hint); +#endif + } + + inline MaybeLocal CopyBuffer( + const char *data + , uint32_t size + ) { + // arbitrary buffer lengths requires + // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION + assert(size <= imp::kMaxLength && "too large buffer"); +#if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION + return node::Buffer::Copy( + v8::Isolate::GetCurrent(), data, size); +#else + return node::Buffer::New(v8::Isolate::GetCurrent(), data, size); +#endif + } + + inline MaybeLocal NewBuffer(uint32_t size) { + // arbitrary buffer lengths requires + // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION + assert(size <= imp::kMaxLength && "too large buffer"); +#if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION + return node::Buffer::New( + v8::Isolate::GetCurrent(), size); +#else + return node::Buffer::New(v8::Isolate::GetCurrent(), size); +#endif + } + + inline MaybeLocal NewBuffer( + char* data + , uint32_t size + ) { + // arbitrary buffer lengths requires + // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION + assert(size <= imp::kMaxLength && "too large buffer"); +#if NODE_MODULE_VERSION > IOJS_2_0_MODULE_VERSION + return node::Buffer::New(v8::Isolate::GetCurrent(), data, size); +#else + return node::Buffer::Use(v8::Isolate::GetCurrent(), data, size); +#endif + } + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + inline MaybeLocal + NewOneByteString(const uint8_t * value, int length = -1) { + return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), value, + v8::NewStringType::kNormal, length); + } + + inline MaybeLocal CompileScript( + v8::Local s + , const v8::ScriptOrigin& origin + ) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + v8::ScriptCompiler::Source source(s, origin); + return scope.Escape( + v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &source) + .FromMaybe(v8::Local())); + } + + inline MaybeLocal CompileScript( + v8::Local s + ) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + v8::ScriptCompiler::Source source(s); + return scope.Escape( + v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &source) + .FromMaybe(v8::Local())); + } + + inline MaybeLocal RunScript( + v8::Local script + ) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(script->BindToCurrentContext() + ->Run(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); + } + + inline MaybeLocal RunScript( + v8::Local script + ) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(script->Run(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); + } +#else + inline MaybeLocal + NewOneByteString(const uint8_t * value, int length = -1) { + return v8::String::NewFromOneByte(v8::Isolate::GetCurrent(), value, + v8::String::kNormalString, length); + } + + inline MaybeLocal CompileScript( + v8::Local s + , const v8::ScriptOrigin& origin + ) { + v8::ScriptCompiler::Source source(s, origin); + return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source); + } + + inline MaybeLocal CompileScript( + v8::Local s + ) { + v8::ScriptCompiler::Source source(s); + return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &source); + } + + inline MaybeLocal RunScript( + v8::Local script + ) { + EscapableHandleScope scope; + return scope.Escape(script->BindToCurrentContext()->Run()); + } + + inline MaybeLocal RunScript( + v8::Local script + ) { + return script->Run(); + } +#endif + + NAN_DEPRECATED inline v8::Local MakeCallback( + v8::Local target + , v8::Local func + , int argc + , v8::Local* argv) { +#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + EscapableHandleScope scope; + return scope.Escape(New(node::MakeCallback( + v8::Isolate::GetCurrent(), target, func, argc, argv))); +#else +# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + AsyncResource res("nan:makeCallback"); + return res.runInAsyncScope(target, func, argc, argv) + .FromMaybe(v8::Local()); +# else + return node::MakeCallback( + v8::Isolate::GetCurrent(), target, func, argc, argv); +# endif // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION +#endif // NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + } + + NAN_DEPRECATED inline v8::Local MakeCallback( + v8::Local target + , v8::Local symbol + , int argc + , v8::Local* argv) { +#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + EscapableHandleScope scope; + return scope.Escape(New(node::MakeCallback( + v8::Isolate::GetCurrent(), target, symbol, argc, argv))); +#else +# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + AsyncResource res("nan:makeCallback"); + return res.runInAsyncScope(target, symbol, argc, argv) + .FromMaybe(v8::Local()); +# else + return node::MakeCallback( + v8::Isolate::GetCurrent(), target, symbol, argc, argv); +# endif // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION +#endif // NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + } + + NAN_DEPRECATED inline v8::Local MakeCallback( + v8::Local target + , const char* method + , int argc + , v8::Local* argv) { +#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + EscapableHandleScope scope; + return scope.Escape(New(node::MakeCallback( + v8::Isolate::GetCurrent(), target, method, argc, argv))); +#else +# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + AsyncResource res("nan:makeCallback"); + return res.runInAsyncScope(target, method, argc, argv) + .FromMaybe(v8::Local()); +# else + return node::MakeCallback( + v8::Isolate::GetCurrent(), target, method, argc, argv); +# endif // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION +#endif // NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + } + + inline void FatalException(const TryCatch& try_catch) { + node::FatalException(v8::Isolate::GetCurrent(), try_catch.try_catch_); + } + + inline v8::Local ErrnoException( + int errorno + , const char* syscall = NULL + , const char* message = NULL + , const char* path = NULL) { + return node::ErrnoException(v8::Isolate::GetCurrent(), errorno, syscall, + message, path); + } + + NAN_DEPRECATED inline v8::Local NanErrnoException( + int errorno + , const char* syscall = NULL + , const char* message = NULL + , const char* path = NULL) { + return ErrnoException(errorno, syscall, message, path); + } + + template + inline void SetIsolateData( + v8::Isolate *isolate + , T *data + ) { + isolate->SetData(0, data); + } + + template + inline T *GetIsolateData( + v8::Isolate *isolate + ) { + return static_cast(isolate->GetData(0)); + } + +class Utf8String { + public: + inline explicit Utf8String(v8::Local from) : + length_(0), str_(str_st_) { + HandleScope scope; + if (!from.IsEmpty()) { +#if NODE_MAJOR_VERSION >= 10 + v8::Local context = GetCurrentContext(); + v8::Local string = + from->ToString(context).FromMaybe(v8::Local()); +#else + v8::Local string = from->ToString(); +#endif + if (!string.IsEmpty()) { + size_t len = 3 * string->Length() + 1; + assert(len <= INT_MAX); + if (len > sizeof (str_st_)) { + str_ = static_cast(malloc(len)); + assert(str_ != 0); + } + const int flags = + v8::String::NO_NULL_TERMINATION | imp::kReplaceInvalidUtf8; +#if NODE_MAJOR_VERSION >= 10 + length_ = string->WriteUtf8(v8::Isolate::GetCurrent(), str_, static_cast(len), 0, flags); +#else + length_ = string->WriteUtf8(str_, static_cast(len), 0, flags); +#endif + str_[length_] = '\0'; + } + } + } + + inline int length() const { + return length_; + } + + inline char* operator*() { return str_; } + inline const char* operator*() const { return str_; } + + inline ~Utf8String() { + if (str_ != str_st_) { + free(str_); + } + } + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(Utf8String) + + int length_; + char *str_; + char str_st_[1024]; +}; + +#else // Node 0.8 and 0.10 + inline v8::Local Undefined() { + EscapableHandleScope scope; + return scope.Escape(New(v8::Undefined())); + } + + inline v8::Local Null() { + EscapableHandleScope scope; + return scope.Escape(New(v8::Null())); + } + + inline v8::Local True() { + EscapableHandleScope scope; + return scope.Escape(New(v8::True())); + } + + inline v8::Local False() { + EscapableHandleScope scope; + return scope.Escape(New(v8::False())); + } + + inline v8::Local EmptyString() { + return v8::String::Empty(); + } + + inline int AdjustExternalMemory(int bc) { + return static_cast(v8::V8::AdjustAmountOfExternalAllocatedMemory(bc)); + } + + inline void SetTemplate( + v8::Local templ + , const char *name + , v8::Local value) { + templ->Set(name, value); + } + + inline void SetTemplate( + v8::Local templ + , v8::Local name + , v8::Local value + , v8::PropertyAttribute attributes) { + templ->Set(name, value, attributes); + } + + inline v8::Local GetCurrentContext() { + return v8::Context::GetCurrent(); + } + + inline void* GetInternalFieldPointer( + v8::Local object + , int index) { + return object->GetPointerFromInternalField(index); + } + + inline void SetInternalFieldPointer( + v8::Local object + , int index + , void* value) { + object->SetPointerInInternalField(index, value); + } + +# define NAN_GC_CALLBACK(name) \ + void name(v8::GCType type, v8::GCCallbackFlags flags) + + inline void AddGCEpilogueCallback( + v8::GCEpilogueCallback callback + , v8::GCType gc_type_filter = v8::kGCTypeAll) { + v8::V8::AddGCEpilogueCallback(callback, gc_type_filter); + } + inline void RemoveGCEpilogueCallback( + v8::GCEpilogueCallback callback) { + v8::V8::RemoveGCEpilogueCallback(callback); + } + inline void AddGCPrologueCallback( + v8::GCPrologueCallback callback + , v8::GCType gc_type_filter = v8::kGCTypeAll) { + v8::V8::AddGCPrologueCallback(callback, gc_type_filter); + } + inline void RemoveGCPrologueCallback( + v8::GCPrologueCallback callback) { + v8::V8::RemoveGCPrologueCallback(callback); + } + inline void GetHeapStatistics( + v8::HeapStatistics *heap_statistics) { + v8::V8::GetHeapStatistics(heap_statistics); + } + +# define X(NAME) \ + inline v8::Local NAME(const char *msg) { \ + EscapableHandleScope scope; \ + return scope.Escape(v8::Exception::NAME(New(msg).ToLocalChecked())); \ + } \ + \ + inline \ + v8::Local NAME(v8::Local msg) { \ + return v8::Exception::NAME(msg); \ + } \ + \ + inline void Throw ## NAME(const char *msg) { \ + HandleScope scope; \ + v8::ThrowException(v8::Exception::NAME(New(msg).ToLocalChecked())); \ + } \ + \ + inline \ + void Throw ## NAME(v8::Local errmsg) { \ + HandleScope scope; \ + v8::ThrowException(v8::Exception::NAME(errmsg)); \ + } + + X(Error) + X(RangeError) + X(ReferenceError) + X(SyntaxError) + X(TypeError) + +# undef X + + inline void ThrowError(v8::Local error) { + v8::ThrowException(error); + } + + inline MaybeLocal NewBuffer( + char *data + , size_t length + , node::Buffer::free_callback callback + , void *hint + ) { + EscapableHandleScope scope; + // arbitrary buffer lengths requires + // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION + assert(length <= imp::kMaxLength && "too large buffer"); + return scope.Escape( + New(node::Buffer::New(data, length, callback, hint)->handle_)); + } + + inline MaybeLocal CopyBuffer( + const char *data + , uint32_t size + ) { + EscapableHandleScope scope; + // arbitrary buffer lengths requires + // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION + assert(size <= imp::kMaxLength && "too large buffer"); +#if NODE_MODULE_VERSION >= NODE_0_10_MODULE_VERSION + return scope.Escape(New(node::Buffer::New(data, size)->handle_)); +#else + return scope.Escape( + New(node::Buffer::New(const_cast(data), size)->handle_)); +#endif + } + + inline MaybeLocal NewBuffer(uint32_t size) { + // arbitrary buffer lengths requires + // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION + EscapableHandleScope scope; + assert(size <= imp::kMaxLength && "too large buffer"); + return scope.Escape(New(node::Buffer::New(size)->handle_)); + } + + inline void FreeData(char *data, void *hint) { + (void) hint; // unused + delete[] data; + } + + inline MaybeLocal NewBuffer( + char* data + , uint32_t size + ) { + EscapableHandleScope scope; + // arbitrary buffer lengths requires + // NODE_MODULE_VERSION >= IOJS_3_0_MODULE_VERSION + assert(size <= imp::kMaxLength && "too large buffer"); + return scope.Escape( + New(node::Buffer::New(data, size, FreeData, NULL)->handle_)); + } + +namespace imp { +inline void +widenString(std::vector *ws, const uint8_t *s, int l) { + size_t len = static_cast(l); + if (l < 0) { + len = strlen(reinterpret_cast(s)); + } + assert(len <= INT_MAX && "string too long"); + ws->resize(len); + std::copy(s, s + len, ws->begin()); // NOLINT(build/include_what_you_use) +} +} // end of namespace imp + + inline MaybeLocal + NewOneByteString(const uint8_t * value, int length = -1) { + std::vector wideString; // NOLINT(build/include_what_you_use) + imp::widenString(&wideString, value, length); + return v8::String::New(wideString.data(), + static_cast(wideString.size())); + } + + inline MaybeLocal CompileScript( + v8::Local s + , const v8::ScriptOrigin& origin + ) { + return v8::Script::Compile(s, const_cast(&origin)); + } + + inline MaybeLocal CompileScript( + v8::Local s + ) { + return v8::Script::Compile(s); + } + + inline + MaybeLocal RunScript(v8::Local script) { + return script->Run(); + } + + inline v8::Local MakeCallback( + v8::Local target + , v8::Local func + , int argc + , v8::Local* argv) { + v8::HandleScope scope; + return scope.Close(New(node::MakeCallback(target, func, argc, argv))); + } + + inline v8::Local MakeCallback( + v8::Local target + , v8::Local symbol + , int argc + , v8::Local* argv) { + v8::HandleScope scope; + return scope.Close(New(node::MakeCallback(target, symbol, argc, argv))); + } + + inline v8::Local MakeCallback( + v8::Local target + , const char* method + , int argc + , v8::Local* argv) { + v8::HandleScope scope; + return scope.Close(New(node::MakeCallback(target, method, argc, argv))); + } + + inline void FatalException(const TryCatch& try_catch) { + node::FatalException(const_cast(try_catch.try_catch_)); + } + + inline v8::Local ErrnoException( + int errorno + , const char* syscall = NULL + , const char* message = NULL + , const char* path = NULL) { + return node::ErrnoException(errorno, syscall, message, path); + } + + NAN_DEPRECATED inline v8::Local NanErrnoException( + int errorno + , const char* syscall = NULL + , const char* message = NULL + , const char* path = NULL) { + return ErrnoException(errorno, syscall, message, path); + } + + + template + inline void SetIsolateData( + v8::Isolate *isolate + , T *data + ) { + isolate->SetData(data); + } + + template + inline T *GetIsolateData( + v8::Isolate *isolate + ) { + return static_cast(isolate->GetData()); + } + +class Utf8String { + public: + inline explicit Utf8String(v8::Local from) : + length_(0), str_(str_st_) { + v8::HandleScope scope; + if (!from.IsEmpty()) { + v8::Local string = from->ToString(); + if (!string.IsEmpty()) { + size_t len = 3 * string->Length() + 1; + assert(len <= INT_MAX); + if (len > sizeof (str_st_)) { + str_ = static_cast(malloc(len)); + assert(str_ != 0); + } + const int flags = + v8::String::NO_NULL_TERMINATION | imp::kReplaceInvalidUtf8; + length_ = string->WriteUtf8(str_, static_cast(len), 0, flags); + str_[length_] = '\0'; + } + } + } + + inline int length() const { + return length_; + } + + inline char* operator*() { return str_; } + inline const char* operator*() const { return str_; } + + inline ~Utf8String() { + if (str_ != str_st_) { + free(str_); + } + } + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(Utf8String) + + int length_; + char *str_; + char str_st_[1024]; +}; + +#endif // NODE_MODULE_VERSION + +typedef void (*FreeCallback)(char *data, void *hint); + +typedef const FunctionCallbackInfo& NAN_METHOD_ARGS_TYPE; +typedef void NAN_METHOD_RETURN_TYPE; + +typedef const PropertyCallbackInfo& NAN_GETTER_ARGS_TYPE; +typedef void NAN_GETTER_RETURN_TYPE; + +typedef const PropertyCallbackInfo& NAN_SETTER_ARGS_TYPE; +typedef void NAN_SETTER_RETURN_TYPE; + +typedef const PropertyCallbackInfo& + NAN_PROPERTY_GETTER_ARGS_TYPE; +typedef void NAN_PROPERTY_GETTER_RETURN_TYPE; + +typedef const PropertyCallbackInfo& + NAN_PROPERTY_SETTER_ARGS_TYPE; +typedef void NAN_PROPERTY_SETTER_RETURN_TYPE; + +typedef const PropertyCallbackInfo& + NAN_PROPERTY_ENUMERATOR_ARGS_TYPE; +typedef void NAN_PROPERTY_ENUMERATOR_RETURN_TYPE; + +typedef const PropertyCallbackInfo& + NAN_PROPERTY_DELETER_ARGS_TYPE; +typedef void NAN_PROPERTY_DELETER_RETURN_TYPE; + +typedef const PropertyCallbackInfo& + NAN_PROPERTY_QUERY_ARGS_TYPE; +typedef void NAN_PROPERTY_QUERY_RETURN_TYPE; + +typedef const PropertyCallbackInfo& NAN_INDEX_GETTER_ARGS_TYPE; +typedef void NAN_INDEX_GETTER_RETURN_TYPE; + +typedef const PropertyCallbackInfo& NAN_INDEX_SETTER_ARGS_TYPE; +typedef void NAN_INDEX_SETTER_RETURN_TYPE; + +typedef const PropertyCallbackInfo& + NAN_INDEX_ENUMERATOR_ARGS_TYPE; +typedef void NAN_INDEX_ENUMERATOR_RETURN_TYPE; + +typedef const PropertyCallbackInfo& + NAN_INDEX_DELETER_ARGS_TYPE; +typedef void NAN_INDEX_DELETER_RETURN_TYPE; + +typedef const PropertyCallbackInfo& + NAN_INDEX_QUERY_ARGS_TYPE; +typedef void NAN_INDEX_QUERY_RETURN_TYPE; + +#define NAN_METHOD(name) \ + Nan::NAN_METHOD_RETURN_TYPE name(Nan::NAN_METHOD_ARGS_TYPE info) +#define NAN_GETTER(name) \ + Nan::NAN_GETTER_RETURN_TYPE name( \ + v8::Local property \ + , Nan::NAN_GETTER_ARGS_TYPE info) +#define NAN_SETTER(name) \ + Nan::NAN_SETTER_RETURN_TYPE name( \ + v8::Local property \ + , v8::Local value \ + , Nan::NAN_SETTER_ARGS_TYPE info) +#define NAN_PROPERTY_GETTER(name) \ + Nan::NAN_PROPERTY_GETTER_RETURN_TYPE name( \ + v8::Local property \ + , Nan::NAN_PROPERTY_GETTER_ARGS_TYPE info) +#define NAN_PROPERTY_SETTER(name) \ + Nan::NAN_PROPERTY_SETTER_RETURN_TYPE name( \ + v8::Local property \ + , v8::Local value \ + , Nan::NAN_PROPERTY_SETTER_ARGS_TYPE info) +#define NAN_PROPERTY_ENUMERATOR(name) \ + Nan::NAN_PROPERTY_ENUMERATOR_RETURN_TYPE name( \ + Nan::NAN_PROPERTY_ENUMERATOR_ARGS_TYPE info) +#define NAN_PROPERTY_DELETER(name) \ + Nan::NAN_PROPERTY_DELETER_RETURN_TYPE name( \ + v8::Local property \ + , Nan::NAN_PROPERTY_DELETER_ARGS_TYPE info) +#define NAN_PROPERTY_QUERY(name) \ + Nan::NAN_PROPERTY_QUERY_RETURN_TYPE name( \ + v8::Local property \ + , Nan::NAN_PROPERTY_QUERY_ARGS_TYPE info) +# define NAN_INDEX_GETTER(name) \ + Nan::NAN_INDEX_GETTER_RETURN_TYPE name( \ + uint32_t index \ + , Nan::NAN_INDEX_GETTER_ARGS_TYPE info) +#define NAN_INDEX_SETTER(name) \ + Nan::NAN_INDEX_SETTER_RETURN_TYPE name( \ + uint32_t index \ + , v8::Local value \ + , Nan::NAN_INDEX_SETTER_ARGS_TYPE info) +#define NAN_INDEX_ENUMERATOR(name) \ + Nan::NAN_INDEX_ENUMERATOR_RETURN_TYPE \ + name(Nan::NAN_INDEX_ENUMERATOR_ARGS_TYPE info) +#define NAN_INDEX_DELETER(name) \ + Nan::NAN_INDEX_DELETER_RETURN_TYPE name( \ + uint32_t index \ + , Nan::NAN_INDEX_DELETER_ARGS_TYPE info) +#define NAN_INDEX_QUERY(name) \ + Nan::NAN_INDEX_QUERY_RETURN_TYPE name( \ + uint32_t index \ + , Nan::NAN_INDEX_QUERY_ARGS_TYPE info) + +class Callback { + public: + Callback() {} + + explicit Callback(const v8::Local &fn) : handle_(fn) {} + + ~Callback() { + handle_.Reset(); + } + + bool operator==(const Callback &other) const { + return handle_ == other.handle_; + } + + bool operator!=(const Callback &other) const { + return !operator==(other); + } + + inline + v8::Local operator*() const { return GetFunction(); } + + NAN_DEPRECATED inline v8::Local operator()( + v8::Local target + , int argc = 0 + , v8::Local argv[] = 0) const { +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + v8::Isolate *isolate = v8::Isolate::GetCurrent(); +# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + AsyncResource async("nan:Callback:operator()"); + return Call_(isolate, target, argc, argv, &async) + .FromMaybe(v8::Local()); +# else + return Call_(isolate, target, argc, argv); +# endif // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION +#else + return Call_(target, argc, argv); +#endif // NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + } + + NAN_DEPRECATED inline v8::Local operator()( + int argc = 0 + , v8::Local argv[] = 0) const { +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); +# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + AsyncResource async("nan:Callback:operator()"); + return scope.Escape(Call_(isolate, isolate->GetCurrentContext()->Global(), + argc, argv, &async) + .FromMaybe(v8::Local())); +# else + return scope.Escape( + Call_(isolate, isolate->GetCurrentContext()->Global(), argc, argv)); +# endif // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION +#else + v8::HandleScope scope; + return scope.Close(Call_(v8::Context::GetCurrent()->Global(), argc, argv)); +#endif // NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + } + + inline MaybeLocal operator()( + AsyncResource* resource + , int argc = 0 + , v8::Local argv[] = 0) const { + return this->Call(argc, argv, resource); + } + + inline MaybeLocal operator()( + AsyncResource* resource + , v8::Local target + , int argc = 0 + , v8::Local argv[] = 0) const { + return this->Call(target, argc, argv, resource); + } + + // TODO(kkoopa): remove + inline void SetFunction(const v8::Local &fn) { + Reset(fn); + } + + inline void Reset(const v8::Local &fn) { + handle_.Reset(fn); + } + + inline void Reset() { + handle_.Reset(); + } + + inline v8::Local GetFunction() const { + return New(handle_); + } + + inline bool IsEmpty() const { + return handle_.IsEmpty(); + } + + // Deprecated: For async callbacks Use the versions that accept an + // AsyncResource. If this callback does not correspond to an async resource, + // that is, it is a synchronous function call on a non-empty JS stack, you + // should Nan::Call instead. + NAN_DEPRECATED inline v8::Local + Call(v8::Local target + , int argc + , v8::Local argv[]) const { +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + v8::Isolate *isolate = v8::Isolate::GetCurrent(); +# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + AsyncResource async("nan:Callback:Call"); + return Call_(isolate, target, argc, argv, &async) + .FromMaybe(v8::Local()); +# else + return Call_(isolate, target, argc, argv); +# endif // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION +#else + return Call_(target, argc, argv); +#endif + } + + // Deprecated: For async callbacks Use the versions that accept an + // AsyncResource. If this callback does not correspond to an async resource, + // that is, it is a synchronous function call on a non-empty JS stack, you + // should Nan::Call instead. + NAN_DEPRECATED inline v8::Local + Call(int argc, v8::Local argv[]) const { +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); +# if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + AsyncResource async("nan:Callback:Call"); + return scope.Escape(Call_(isolate, isolate->GetCurrentContext()->Global(), + argc, argv, &async) + .FromMaybe(v8::Local())); +# else + return scope.Escape( + Call_(isolate, isolate->GetCurrentContext()->Global(), argc, argv)); +# endif // NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION +#else + v8::HandleScope scope; + return scope.Close(Call_(v8::Context::GetCurrent()->Global(), argc, argv)); +#endif + } + + inline MaybeLocal + Call(v8::Local target + , int argc + , v8::Local argv[] + , AsyncResource* resource) const { +#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + return Call_(isolate, target, argc, argv, resource); +#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + return Call_(isolate, target, argc, argv); +#else + return Call_(target, argc, argv); +#endif + } + + inline MaybeLocal + Call(int argc, v8::Local argv[], AsyncResource* resource) const { +#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + return Call(isolate->GetCurrentContext()->Global(), argc, argv, resource); +#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape( + Call_(isolate, isolate->GetCurrentContext()->Global(), argc, argv)); +#else + v8::HandleScope scope; + return scope.Close(Call_(v8::Context::GetCurrent()->Global(), argc, argv)); +#endif + } + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(Callback) + Persistent handle_; + +#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + MaybeLocal Call_(v8::Isolate *isolate + , v8::Local target + , int argc + , v8::Local argv[] + , AsyncResource* resource) const { + EscapableHandleScope scope; + v8::Local func = New(handle_); + auto maybe = resource->runInAsyncScope(target, func, argc, argv); + v8::Local local; + if (!maybe.ToLocal(&local)) return MaybeLocal(); + return scope.Escape(local); + } +#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + v8::Local Call_(v8::Isolate *isolate + , v8::Local target + , int argc + , v8::Local argv[]) const { + EscapableHandleScope scope; + + v8::Local callback = New(handle_); +# if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION + return scope.Escape(New(node::MakeCallback( + isolate + , target + , callback + , argc + , argv + ))); +# else + return scope.Escape(node::MakeCallback( + isolate + , target + , callback + , argc + , argv + )); +# endif + } +#else + v8::Local Call_(v8::Local target + , int argc + , v8::Local argv[]) const { + EscapableHandleScope scope; + + v8::Local callback = New(handle_); + return scope.Escape(New(node::MakeCallback( + target + , callback + , argc + , argv + ))); + } +#endif +}; + +inline MaybeLocal Call( + const Nan::Callback& callback + , v8::Local recv + , int argc + , v8::Local argv[]) { + return Call(*callback, recv, argc, argv); +} + +inline MaybeLocal Call( + const Nan::Callback& callback + , int argc + , v8::Local argv[]) { +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape( + Call(*callback, isolate->GetCurrentContext()->Global(), argc, argv) + .FromMaybe(v8::Local())); +#else + EscapableHandleScope scope; + return scope.Escape( + Call(*callback, v8::Context::GetCurrent()->Global(), argc, argv) + .FromMaybe(v8::Local())); +#endif +} + +inline MaybeLocal Call( + v8::Local symbol + , v8::Local recv + , int argc + , v8::Local argv[]) { + EscapableHandleScope scope; + v8::Local fn_v = + Get(recv, symbol).FromMaybe(v8::Local()); + if (fn_v.IsEmpty() || !fn_v->IsFunction()) return v8::Local(); + v8::Local fn = fn_v.As(); + return scope.Escape( + Call(fn, recv, argc, argv).FromMaybe(v8::Local())); +} + +inline MaybeLocal Call( + const char* method + , v8::Local recv + , int argc + , v8::Local argv[]) { + EscapableHandleScope scope; + v8::Local method_string = + New(method).ToLocalChecked(); + return scope.Escape( + Call(method_string, recv, argc, argv).FromMaybe(v8::Local())); +} + +/* abstract */ class AsyncWorker { + public: + explicit AsyncWorker(Callback *callback_, + const char* resource_name = "nan:AsyncWorker") + : callback(callback_), errmsg_(NULL) { + request.data = this; + + HandleScope scope; + v8::Local obj = New(); + persistentHandle.Reset(obj); + async_resource = new AsyncResource(resource_name, obj); + } + + virtual ~AsyncWorker() { + HandleScope scope; + + if (!persistentHandle.IsEmpty()) + persistentHandle.Reset(); + delete callback; + delete[] errmsg_; + delete async_resource; + } + + virtual void WorkComplete() { + HandleScope scope; + + if (errmsg_ == NULL) + HandleOKCallback(); + else + HandleErrorCallback(); + delete callback; + callback = NULL; + } + + inline void SaveToPersistent( + const char *key, const v8::Local &value) { + HandleScope scope; + Set(New(persistentHandle), New(key).ToLocalChecked(), value).FromJust(); + } + + inline void SaveToPersistent( + const v8::Local &key, const v8::Local &value) { + HandleScope scope; + Set(New(persistentHandle), key, value).FromJust(); + } + + inline void SaveToPersistent( + uint32_t index, const v8::Local &value) { + HandleScope scope; + Set(New(persistentHandle), index, value).FromJust(); + } + + inline v8::Local GetFromPersistent(const char *key) const { + EscapableHandleScope scope; + return scope.Escape( + Get(New(persistentHandle), New(key).ToLocalChecked()) + .FromMaybe(v8::Local())); + } + + inline v8::Local + GetFromPersistent(const v8::Local &key) const { + EscapableHandleScope scope; + return scope.Escape( + Get(New(persistentHandle), key) + .FromMaybe(v8::Local())); + } + + inline v8::Local GetFromPersistent(uint32_t index) const { + EscapableHandleScope scope; + return scope.Escape( + Get(New(persistentHandle), index) + .FromMaybe(v8::Local())); + } + + virtual void Execute() = 0; + + uv_work_t request; + + virtual void Destroy() { + delete this; + } + + protected: + Persistent persistentHandle; + Callback *callback; + AsyncResource *async_resource; + + virtual void HandleOKCallback() { + HandleScope scope; + + callback->Call(0, NULL, async_resource); + } + + virtual void HandleErrorCallback() { + HandleScope scope; + + v8::Local argv[] = { + v8::Exception::Error(New(ErrorMessage()).ToLocalChecked()) + }; + callback->Call(1, argv, async_resource); + } + + void SetErrorMessage(const char *msg) { + delete[] errmsg_; + + size_t size = strlen(msg) + 1; + errmsg_ = new char[size]; + memcpy(errmsg_, msg, size); + } + + const char* ErrorMessage() const { + return errmsg_; + } + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(AsyncWorker) + char *errmsg_; +}; + +/* abstract */ class AsyncBareProgressWorkerBase : public AsyncWorker { + public: + explicit AsyncBareProgressWorkerBase( + Callback *callback_, + const char* resource_name = "nan:AsyncBareProgressWorkerBase") + : AsyncWorker(callback_, resource_name) { + uv_async_init( + GetCurrentEventLoop() + , &async + , AsyncProgress_ + ); + async.data = this; + } + + virtual ~AsyncBareProgressWorkerBase() { + } + + virtual void WorkProgress() = 0; + + virtual void Destroy() { + uv_close(reinterpret_cast(&async), AsyncClose_); + } + + private: + inline static NAUV_WORK_CB(AsyncProgress_) { + AsyncBareProgressWorkerBase *worker = + static_cast(async->data); + worker->WorkProgress(); + } + + inline static void AsyncClose_(uv_handle_t* handle) { + AsyncBareProgressWorkerBase *worker = + static_cast(handle->data); + delete worker; + } + + protected: + uv_async_t async; +}; + +template +/* abstract */ +class AsyncBareProgressWorker : public AsyncBareProgressWorkerBase { + public: + explicit AsyncBareProgressWorker( + Callback *callback_, + const char* resource_name = "nan:AsyncBareProgressWorker") + : AsyncBareProgressWorkerBase(callback_, resource_name) { + uv_mutex_init(&async_lock); + } + + virtual ~AsyncBareProgressWorker() { + uv_mutex_destroy(&async_lock); + } + + class ExecutionProgress { + friend class AsyncBareProgressWorker; + public: + void Signal() const { + uv_mutex_lock(&that_->async_lock); + uv_async_send(&that_->async); + uv_mutex_unlock(&that_->async_lock); + } + + void Send(const T* data, size_t count) const { + that_->SendProgress_(data, count); + } + + private: + explicit ExecutionProgress(AsyncBareProgressWorker *that) : that_(that) {} + NAN_DISALLOW_ASSIGN_COPY_MOVE(ExecutionProgress) + AsyncBareProgressWorker* const that_; + }; + + virtual void Execute(const ExecutionProgress& progress) = 0; + virtual void HandleProgressCallback(const T *data, size_t size) = 0; + + protected: + uv_mutex_t async_lock; + + private: + void Execute() /*final override*/ { + ExecutionProgress progress(this); + Execute(progress); + } + + virtual void SendProgress_(const T *data, size_t count) = 0; +}; + +template +/* abstract */ +class AsyncProgressWorkerBase : public AsyncBareProgressWorker { + public: + explicit AsyncProgressWorkerBase( + Callback *callback_, + const char* resource_name = "nan:AsyncProgressWorkerBase") + : AsyncBareProgressWorker(callback_, resource_name), asyncdata_(NULL), + asyncsize_(0) { + } + + virtual ~AsyncProgressWorkerBase() { + delete[] asyncdata_; + } + + void WorkProgress() { + uv_mutex_lock(&this->async_lock); + T *data = asyncdata_; + size_t size = asyncsize_; + asyncdata_ = NULL; + asyncsize_ = 0; + uv_mutex_unlock(&this->async_lock); + + // Don't send progress events after we've already completed. + if (this->callback) { + this->HandleProgressCallback(data, size); + } + delete[] data; + } + + private: + void SendProgress_(const T *data, size_t count) { + T *new_data = new T[count]; + { + T *it = new_data; + std::copy(data, data + count, it); + } + + uv_mutex_lock(&this->async_lock); + T *old_data = asyncdata_; + asyncdata_ = new_data; + asyncsize_ = count; + uv_async_send(&this->async); + uv_mutex_unlock(&this->async_lock); + + delete[] old_data; + } + + T *asyncdata_; + size_t asyncsize_; +}; + +// This ensures compatibility to the previous un-templated AsyncProgressWorker +// class definition. +typedef AsyncProgressWorkerBase AsyncProgressWorker; + +template +/* abstract */ +class AsyncBareProgressQueueWorker : public AsyncBareProgressWorkerBase { + public: + explicit AsyncBareProgressQueueWorker( + Callback *callback_, + const char* resource_name = "nan:AsyncBareProgressQueueWorker") + : AsyncBareProgressWorkerBase(callback_, resource_name) { + } + + virtual ~AsyncBareProgressQueueWorker() { + } + + class ExecutionProgress { + friend class AsyncBareProgressQueueWorker; + public: + void Send(const T* data, size_t count) const { + that_->SendProgress_(data, count); + } + + private: + explicit ExecutionProgress(AsyncBareProgressQueueWorker *that) + : that_(that) {} + NAN_DISALLOW_ASSIGN_COPY_MOVE(ExecutionProgress) + AsyncBareProgressQueueWorker* const that_; + }; + + virtual void Execute(const ExecutionProgress& progress) = 0; + virtual void HandleProgressCallback(const T *data, size_t size) = 0; + + private: + void Execute() /*final override*/ { + ExecutionProgress progress(this); + Execute(progress); + } + + virtual void SendProgress_(const T *data, size_t count) = 0; +}; + +template +/* abstract */ +class AsyncProgressQueueWorker : public AsyncBareProgressQueueWorker { + public: + explicit AsyncProgressQueueWorker( + Callback *callback_, + const char* resource_name = "nan:AsyncProgressQueueWorker") + : AsyncBareProgressQueueWorker(callback_) { + uv_mutex_init(&async_lock); + } + + virtual ~AsyncProgressQueueWorker() { + uv_mutex_lock(&async_lock); + + while (!asyncdata_.empty()) { + std::pair &datapair = asyncdata_.front(); + T *data = datapair.first; + + asyncdata_.pop(); + + delete[] data; + } + + uv_mutex_unlock(&async_lock); + uv_mutex_destroy(&async_lock); + } + + void WorkComplete() { + WorkProgress(); + AsyncWorker::WorkComplete(); + } + + void WorkProgress() { + uv_mutex_lock(&async_lock); + + while (!asyncdata_.empty()) { + std::pair &datapair = asyncdata_.front(); + + T *data = datapair.first; + size_t size = datapair.second; + + asyncdata_.pop(); + uv_mutex_unlock(&async_lock); + + // Don't send progress events after we've already completed. + if (this->callback) { + this->HandleProgressCallback(data, size); + } + + delete[] data; + + uv_mutex_lock(&async_lock); + } + + uv_mutex_unlock(&async_lock); + } + + private: + void SendProgress_(const T *data, size_t count) { + T *new_data = new T[count]; + { + T *it = new_data; + std::copy(data, data + count, it); + } + + uv_mutex_lock(&async_lock); + asyncdata_.push(std::pair(new_data, count)); + uv_mutex_unlock(&async_lock); + + uv_async_send(&this->async); + } + + uv_mutex_t async_lock; + std::queue > asyncdata_; +}; + +inline void AsyncExecute (uv_work_t* req) { + AsyncWorker *worker = static_cast(req->data); + worker->Execute(); +} + +inline void AsyncExecuteComplete (uv_work_t* req) { + AsyncWorker* worker = static_cast(req->data); + worker->WorkComplete(); + worker->Destroy(); +} + +inline void AsyncQueueWorker (AsyncWorker* worker) { + uv_queue_work( + GetCurrentEventLoop() + , &worker->request + , AsyncExecute + , reinterpret_cast(AsyncExecuteComplete) + ); +} + +namespace imp { + +inline +ExternalOneByteStringResource const* +GetExternalResource(v8::Local str) { +#if NODE_MODULE_VERSION < ATOM_0_21_MODULE_VERSION + return str->GetExternalAsciiStringResource(); +#else + return str->GetExternalOneByteStringResource(); +#endif +} + +inline +bool +IsExternal(v8::Local str) { +#if NODE_MODULE_VERSION < ATOM_0_21_MODULE_VERSION + return str->IsExternalAscii(); +#else + return str->IsExternalOneByte(); +#endif +} + +} // end of namespace imp + +enum Encoding {ASCII, UTF8, BASE64, UCS2, BINARY, HEX, BUFFER}; + +#if NODE_MODULE_VERSION < NODE_0_10_MODULE_VERSION +# include "nan_string_bytes.h" // NOLINT(build/include) +#endif + +inline v8::Local Encode( + const void *buf, size_t len, enum Encoding encoding = BINARY) { +#if (NODE_MODULE_VERSION >= ATOM_0_21_MODULE_VERSION) + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + node::encoding node_enc = static_cast(encoding); + + if (encoding == UCS2) { + return node::Encode( + isolate + , reinterpret_cast(buf) + , len / 2); + } else { + return node::Encode( + isolate + , reinterpret_cast(buf) + , len + , node_enc); + } +#elif (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION) + return node::Encode( + v8::Isolate::GetCurrent() + , buf, len + , static_cast(encoding)); +#else +# if NODE_MODULE_VERSION >= NODE_0_10_MODULE_VERSION + return node::Encode(buf, len, static_cast(encoding)); +# else + return imp::Encode(reinterpret_cast(buf), len, encoding); +# endif +#endif +} + +inline ssize_t DecodeBytes( + v8::Local val, enum Encoding encoding = BINARY) { +#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION) + return node::DecodeBytes( + v8::Isolate::GetCurrent() + , val + , static_cast(encoding)); +#else +# if (NODE_MODULE_VERSION < NODE_0_10_MODULE_VERSION) + if (encoding == BUFFER) { + return node::DecodeBytes(val, node::BINARY); + } +# endif + return node::DecodeBytes(val, static_cast(encoding)); +#endif +} + +inline ssize_t DecodeWrite( + char *buf + , size_t len + , v8::Local val + , enum Encoding encoding = BINARY) { +#if (NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION) + return node::DecodeWrite( + v8::Isolate::GetCurrent() + , buf + , len + , val + , static_cast(encoding)); +#else +# if (NODE_MODULE_VERSION < NODE_0_10_MODULE_VERSION) + if (encoding == BUFFER) { + return node::DecodeWrite(buf, len, val, node::BINARY); + } +# endif + return node::DecodeWrite( + buf + , len + , val + , static_cast(encoding)); +#endif +} + +inline void SetPrototypeTemplate( + v8::Local templ + , const char *name + , v8::Local value +) { + HandleScope scope; + SetTemplate(templ->PrototypeTemplate(), name, value); +} + +inline void SetPrototypeTemplate( + v8::Local templ + , v8::Local name + , v8::Local value + , v8::PropertyAttribute attributes +) { + HandleScope scope; + SetTemplate(templ->PrototypeTemplate(), name, value, attributes); +} + +inline void SetInstanceTemplate( + v8::Local templ + , const char *name + , v8::Local value +) { + HandleScope scope; + SetTemplate(templ->InstanceTemplate(), name, value); +} + +inline void SetInstanceTemplate( + v8::Local templ + , v8::Local name + , v8::Local value + , v8::PropertyAttribute attributes +) { + HandleScope scope; + SetTemplate(templ->InstanceTemplate(), name, value, attributes); +} + +namespace imp { + +// Note(@agnat): Helper to distinguish different receiver types. The first +// version deals with receivers derived from v8::Template. The second version +// handles everything else. The final argument only serves as discriminator and +// is unused. +template +inline +void +SetMethodAux(T recv, + v8::Local name, + v8::Local tpl, + v8::Template *) { + recv->Set(name, tpl); +} + +template +inline +void +SetMethodAux(T recv, + v8::Local name, + v8::Local tpl, + ...) { + Set(recv, name, GetFunction(tpl).ToLocalChecked()); +} + +} // end of namespace imp + +template class HandleType> +inline void SetMethod( + HandleType recv + , const char *name + , FunctionCallback callback) { + HandleScope scope; + v8::Local t = New(callback); + v8::Local fn_name = New(name).ToLocalChecked(); + t->SetClassName(fn_name); + // Note(@agnat): Pass an empty T* as discriminator. See note on + // SetMethodAux(...) above + imp::SetMethodAux(recv, fn_name, t, static_cast(0)); +} + +inline void SetPrototypeMethod( + v8::Local recv + , const char* name, FunctionCallback callback) { + HandleScope scope; + v8::Local t = New( + callback + , v8::Local() + , New(recv)); + v8::Local fn_name = New(name).ToLocalChecked(); + recv->PrototypeTemplate()->Set(fn_name, t); + t->SetClassName(fn_name); +} + +//=== Accessors and Such ======================================================= + +inline void SetAccessor( + v8::Local tpl + , v8::Local name + , GetterCallback getter + , SetterCallback setter = 0 + , v8::Local data = v8::Local() + , v8::AccessControl settings = v8::DEFAULT + , v8::PropertyAttribute attribute = v8::None + , imp::Sig signature = imp::Sig()) { + HandleScope scope; + + imp::NativeGetter getter_ = + imp::GetterCallbackWrapper; + imp::NativeSetter setter_ = + setter ? imp::SetterCallbackWrapper : 0; + + v8::Local otpl = New(); + otpl->SetInternalFieldCount(imp::kAccessorFieldCount); + v8::Local obj = NewInstance(otpl).ToLocalChecked(); + + obj->SetInternalField( + imp::kGetterIndex + , New(reinterpret_cast(getter))); + + if (setter != 0) { + obj->SetInternalField( + imp::kSetterIndex + , New(reinterpret_cast(setter))); + } + + if (!data.IsEmpty()) { + obj->SetInternalField(imp::kDataIndex, data); + } + + tpl->SetAccessor( + name + , getter_ + , setter_ + , obj + , settings + , attribute + , signature); +} + +inline bool SetAccessor( + v8::Local obj + , v8::Local name + , GetterCallback getter + , SetterCallback setter = 0 + , v8::Local data = v8::Local() + , v8::AccessControl settings = v8::DEFAULT + , v8::PropertyAttribute attribute = v8::None) { + HandleScope scope; + + imp::NativeGetter getter_ = + imp::GetterCallbackWrapper; + imp::NativeSetter setter_ = + setter ? imp::SetterCallbackWrapper : 0; + + v8::Local otpl = New(); + otpl->SetInternalFieldCount(imp::kAccessorFieldCount); + v8::Local dataobj = NewInstance(otpl).ToLocalChecked(); + + dataobj->SetInternalField( + imp::kGetterIndex + , New(reinterpret_cast(getter))); + + if (!data.IsEmpty()) { + dataobj->SetInternalField(imp::kDataIndex, data); + } + + if (setter) { + dataobj->SetInternalField( + imp::kSetterIndex + , New(reinterpret_cast(setter))); + } + +#if (NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION) + return obj->SetAccessor( + GetCurrentContext() + , name + , getter_ + , setter_ + , dataobj + , settings + , attribute).FromMaybe(false); +#else + return obj->SetAccessor( + name + , getter_ + , setter_ + , dataobj + , settings + , attribute); +#endif +} + +inline void SetNamedPropertyHandler( + v8::Local tpl + , PropertyGetterCallback getter + , PropertySetterCallback setter = 0 + , PropertyQueryCallback query = 0 + , PropertyDeleterCallback deleter = 0 + , PropertyEnumeratorCallback enumerator = 0 + , v8::Local data = v8::Local()) { + HandleScope scope; + + imp::NativePropertyGetter getter_ = + imp::PropertyGetterCallbackWrapper; + imp::NativePropertySetter setter_ = + setter ? imp::PropertySetterCallbackWrapper : 0; + imp::NativePropertyQuery query_ = + query ? imp::PropertyQueryCallbackWrapper : 0; + imp::NativePropertyDeleter *deleter_ = + deleter ? imp::PropertyDeleterCallbackWrapper : 0; + imp::NativePropertyEnumerator enumerator_ = + enumerator ? imp::PropertyEnumeratorCallbackWrapper : 0; + + v8::Local otpl = New(); + otpl->SetInternalFieldCount(imp::kPropertyFieldCount); + v8::Local obj = NewInstance(otpl).ToLocalChecked(); + obj->SetInternalField( + imp::kPropertyGetterIndex + , New(reinterpret_cast(getter))); + + if (setter) { + obj->SetInternalField( + imp::kPropertySetterIndex + , New(reinterpret_cast(setter))); + } + + if (query) { + obj->SetInternalField( + imp::kPropertyQueryIndex + , New(reinterpret_cast(query))); + } + + if (deleter) { + obj->SetInternalField( + imp::kPropertyDeleterIndex + , New(reinterpret_cast(deleter))); + } + + if (enumerator) { + obj->SetInternalField( + imp::kPropertyEnumeratorIndex + , New(reinterpret_cast(enumerator))); + } + + if (!data.IsEmpty()) { + obj->SetInternalField(imp::kDataIndex, data); + } + +#if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION + tpl->SetHandler(v8::NamedPropertyHandlerConfiguration( + getter_, setter_, query_, deleter_, enumerator_, obj)); +#else + tpl->SetNamedPropertyHandler( + getter_ + , setter_ + , query_ + , deleter_ + , enumerator_ + , obj); +#endif +} + +inline void SetIndexedPropertyHandler( + v8::Local tpl + , IndexGetterCallback getter + , IndexSetterCallback setter = 0 + , IndexQueryCallback query = 0 + , IndexDeleterCallback deleter = 0 + , IndexEnumeratorCallback enumerator = 0 + , v8::Local data = v8::Local()) { + HandleScope scope; + + imp::NativeIndexGetter getter_ = + imp::IndexGetterCallbackWrapper; + imp::NativeIndexSetter setter_ = + setter ? imp::IndexSetterCallbackWrapper : 0; + imp::NativeIndexQuery query_ = + query ? imp::IndexQueryCallbackWrapper : 0; + imp::NativeIndexDeleter deleter_ = + deleter ? imp::IndexDeleterCallbackWrapper : 0; + imp::NativeIndexEnumerator enumerator_ = + enumerator ? imp::IndexEnumeratorCallbackWrapper : 0; + + v8::Local otpl = New(); + otpl->SetInternalFieldCount(imp::kIndexPropertyFieldCount); + v8::Local obj = NewInstance(otpl).ToLocalChecked(); + obj->SetInternalField( + imp::kIndexPropertyGetterIndex + , New(reinterpret_cast(getter))); + + if (setter) { + obj->SetInternalField( + imp::kIndexPropertySetterIndex + , New(reinterpret_cast(setter))); + } + + if (query) { + obj->SetInternalField( + imp::kIndexPropertyQueryIndex + , New(reinterpret_cast(query))); + } + + if (deleter) { + obj->SetInternalField( + imp::kIndexPropertyDeleterIndex + , New(reinterpret_cast(deleter))); + } + + if (enumerator) { + obj->SetInternalField( + imp::kIndexPropertyEnumeratorIndex + , New(reinterpret_cast(enumerator))); + } + + if (!data.IsEmpty()) { + obj->SetInternalField(imp::kDataIndex, data); + } + +#if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION + tpl->SetHandler(v8::IndexedPropertyHandlerConfiguration( + getter_, setter_, query_, deleter_, enumerator_, obj)); +#else + tpl->SetIndexedPropertyHandler( + getter_ + , setter_ + , query_ + , deleter_ + , enumerator_ + , obj); +#endif +} + +inline void SetCallHandler( + v8::Local tpl + , FunctionCallback callback + , v8::Local data = v8::Local()) { + HandleScope scope; + + v8::Local otpl = New(); + otpl->SetInternalFieldCount(imp::kFunctionFieldCount); + v8::Local obj = NewInstance(otpl).ToLocalChecked(); + + obj->SetInternalField( + imp::kFunctionIndex + , New(reinterpret_cast(callback))); + + if (!data.IsEmpty()) { + obj->SetInternalField(imp::kDataIndex, data); + } + + tpl->SetCallHandler(imp::FunctionCallbackWrapper, obj); +} + + +inline void SetCallAsFunctionHandler( + v8::Local tpl, + FunctionCallback callback, + v8::Local data = v8::Local()) { + HandleScope scope; + + v8::Local otpl = New(); + otpl->SetInternalFieldCount(imp::kFunctionFieldCount); + v8::Local obj = NewInstance(otpl).ToLocalChecked(); + + obj->SetInternalField( + imp::kFunctionIndex + , New(reinterpret_cast(callback))); + + if (!data.IsEmpty()) { + obj->SetInternalField(imp::kDataIndex, data); + } + + tpl->SetCallAsFunctionHandler(imp::FunctionCallbackWrapper, obj); +} + +//=== Weak Persistent Handling ================================================= + +#include "nan_weak.h" // NOLINT(build/include) + +//=== ObjectWrap =============================================================== + +#include "nan_object_wrap.h" // NOLINT(build/include) + +//=== HiddenValue/Private ====================================================== + +#include "nan_private.h" // NOLINT(build/include) + +//=== Export ================================================================== + +inline +void +Export(ADDON_REGISTER_FUNCTION_ARGS_TYPE target, const char *name, + FunctionCallback f) { + HandleScope scope; + + Set(target, New(name).ToLocalChecked(), + GetFunction(New(f)).ToLocalChecked()); +} + +//=== Tap Reverse Binding ===================================================== + +struct Tap { + explicit Tap(v8::Local t) : t_() { + HandleScope scope; + + t_.Reset(To(t).ToLocalChecked()); + } + + ~Tap() { t_.Reset(); } // not sure if neccessary + + inline void plan(int i) { + HandleScope scope; + v8::Local arg = New(i); + Call("plan", New(t_), 1, &arg); + } + + inline void ok(bool isOk, const char *msg = NULL) { + HandleScope scope; + v8::Local args[2]; + args[0] = New(isOk); + if (msg) args[1] = New(msg).ToLocalChecked(); + Call("ok", New(t_), msg ? 2 : 1, args); + } + + inline void pass(const char * msg = NULL) { + HandleScope scope; + v8::Local hmsg; + if (msg) hmsg = New(msg).ToLocalChecked(); + Call("pass", New(t_), msg ? 1 : 0, &hmsg); + } + + inline void end() { + HandleScope scope; + Call("end", New(t_), 0, NULL); + } + + private: + Persistent t_; +}; + +#define NAN_STRINGIZE2(x) #x +#define NAN_STRINGIZE(x) NAN_STRINGIZE2(x) +#define NAN_TEST_EXPRESSION(expression) \ + ( expression ), __FILE__ ":" NAN_STRINGIZE(__LINE__) ": " #expression + +#define NAN_EXPORT(target, function) Export(target, #function, function) + +#undef TYPE_CHECK + +//=== Generic Maybefication =================================================== + +namespace imp { + +template struct Maybefier; + +template struct Maybefier > { + inline static MaybeLocal convert(v8::Local v) { + return v; + } +}; + +template struct Maybefier > { + inline static MaybeLocal convert(MaybeLocal v) { + return v; + } +}; + +} // end of namespace imp + +template class MaybeMaybe> +inline MaybeLocal +MakeMaybe(MaybeMaybe v) { + return imp::Maybefier >::convert(v); +} + +//=== TypedArrayContents ======================================================= + +#include "nan_typedarray_contents.h" // NOLINT(build/include) + +//=== JSON ===================================================================== + +#include "nan_json.h" // NOLINT(build/include) + +} // end of namespace Nan + +#endif // NAN_H_ diff --git a/express-server/node_modules/nan/nan_callbacks.h b/express-server/node_modules/nan/nan_callbacks.h new file mode 100644 index 00000000..53ede846 --- /dev/null +++ b/express-server/node_modules/nan/nan_callbacks.h @@ -0,0 +1,88 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_CALLBACKS_H_ +#define NAN_CALLBACKS_H_ + +template class FunctionCallbackInfo; +template class PropertyCallbackInfo; +template class Global; + +typedef void(*FunctionCallback)(const FunctionCallbackInfo&); +typedef void(*GetterCallback) + (v8::Local, const PropertyCallbackInfo&); +typedef void(*SetterCallback)( + v8::Local, + v8::Local, + const PropertyCallbackInfo&); +typedef void(*PropertyGetterCallback)( + v8::Local, + const PropertyCallbackInfo&); +typedef void(*PropertySetterCallback)( + v8::Local, + v8::Local, + const PropertyCallbackInfo&); +typedef void(*PropertyEnumeratorCallback) + (const PropertyCallbackInfo&); +typedef void(*PropertyDeleterCallback)( + v8::Local, + const PropertyCallbackInfo&); +typedef void(*PropertyQueryCallback)( + v8::Local, + const PropertyCallbackInfo&); +typedef void(*IndexGetterCallback)( + uint32_t, + const PropertyCallbackInfo&); +typedef void(*IndexSetterCallback)( + uint32_t, + v8::Local, + const PropertyCallbackInfo&); +typedef void(*IndexEnumeratorCallback) + (const PropertyCallbackInfo&); +typedef void(*IndexDeleterCallback)( + uint32_t, + const PropertyCallbackInfo&); +typedef void(*IndexQueryCallback)( + uint32_t, + const PropertyCallbackInfo&); + +namespace imp { +typedef v8::Local Sig; + +static const int kDataIndex = 0; + +static const int kFunctionIndex = 1; +static const int kFunctionFieldCount = 2; + +static const int kGetterIndex = 1; +static const int kSetterIndex = 2; +static const int kAccessorFieldCount = 3; + +static const int kPropertyGetterIndex = 1; +static const int kPropertySetterIndex = 2; +static const int kPropertyEnumeratorIndex = 3; +static const int kPropertyDeleterIndex = 4; +static const int kPropertyQueryIndex = 5; +static const int kPropertyFieldCount = 6; + +static const int kIndexPropertyGetterIndex = 1; +static const int kIndexPropertySetterIndex = 2; +static const int kIndexPropertyEnumeratorIndex = 3; +static const int kIndexPropertyDeleterIndex = 4; +static const int kIndexPropertyQueryIndex = 5; +static const int kIndexPropertyFieldCount = 6; + +} // end of namespace imp + +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION +# include "nan_callbacks_12_inl.h" // NOLINT(build/include) +#else +# include "nan_callbacks_pre_12_inl.h" // NOLINT(build/include) +#endif + +#endif // NAN_CALLBACKS_H_ diff --git a/express-server/node_modules/nan/nan_callbacks_12_inl.h b/express-server/node_modules/nan/nan_callbacks_12_inl.h new file mode 100644 index 00000000..c27b18d8 --- /dev/null +++ b/express-server/node_modules/nan/nan_callbacks_12_inl.h @@ -0,0 +1,514 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_CALLBACKS_12_INL_H_ +#define NAN_CALLBACKS_12_INL_H_ + +template +class ReturnValue { + v8::ReturnValue value_; + + public: + template + explicit inline ReturnValue(const v8::ReturnValue &value) : + value_(value) {} + template + explicit inline ReturnValue(const ReturnValue& that) + : value_(that.value_) { + TYPE_CHECK(T, S); + } + + // Handle setters + template inline void Set(const v8::Local &handle) { + TYPE_CHECK(T, S); + value_.Set(handle); + } + + template inline void Set(const Global &handle) { + TYPE_CHECK(T, S); +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && \ + (V8_MINOR_VERSION > 5 || (V8_MINOR_VERSION == 5 && \ + defined(V8_BUILD_NUMBER) && V8_BUILD_NUMBER >= 8)))) + value_.Set(handle); +#else + value_.Set(*reinterpret_cast*>(&handle)); + const_cast &>(handle).Reset(); +#endif + } + + // Fast primitive setters + inline void Set(bool value) { + TYPE_CHECK(T, v8::Boolean); + value_.Set(value); + } + + inline void Set(double i) { + TYPE_CHECK(T, v8::Number); + value_.Set(i); + } + + inline void Set(int32_t i) { + TYPE_CHECK(T, v8::Integer); + value_.Set(i); + } + + inline void Set(uint32_t i) { + TYPE_CHECK(T, v8::Integer); + value_.Set(i); + } + + // Fast JS primitive setters + inline void SetNull() { + TYPE_CHECK(T, v8::Primitive); + value_.SetNull(); + } + + inline void SetUndefined() { + TYPE_CHECK(T, v8::Primitive); + value_.SetUndefined(); + } + + inline void SetEmptyString() { + TYPE_CHECK(T, v8::String); + value_.SetEmptyString(); + } + + // Convenience getter for isolate + inline v8::Isolate *GetIsolate() const { + return value_.GetIsolate(); + } + + // Pointer setter: Uncompilable to prevent inadvertent misuse. + template + inline void Set(S *whatever) { TYPE_CHECK(S*, v8::Primitive); } +}; + +template +class FunctionCallbackInfo { + const v8::FunctionCallbackInfo &info_; + const v8::Local data_; + + public: + explicit inline FunctionCallbackInfo( + const v8::FunctionCallbackInfo &info + , v8::Local data) : + info_(info) + , data_(data) {} + + inline ReturnValue GetReturnValue() const { + return ReturnValue(info_.GetReturnValue()); + } + +#if NODE_MAJOR_VERSION < 10 + inline v8::Local Callee() const { return info_.Callee(); } +#endif + inline v8::Local Data() const { return data_; } + inline v8::Local Holder() const { return info_.Holder(); } + inline bool IsConstructCall() const { return info_.IsConstructCall(); } + inline int Length() const { return info_.Length(); } + inline v8::Local operator[](int i) const { return info_[i]; } + inline v8::Local This() const { return info_.This(); } + inline v8::Isolate *GetIsolate() const { return info_.GetIsolate(); } + + + protected: + static const int kHolderIndex = 0; + static const int kIsolateIndex = 1; + static const int kReturnValueDefaultValueIndex = 2; + static const int kReturnValueIndex = 3; + static const int kDataIndex = 4; + static const int kCalleeIndex = 5; + static const int kContextSaveIndex = 6; + static const int kArgsLength = 7; + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(FunctionCallbackInfo) +}; + +template +class PropertyCallbackInfo { + const v8::PropertyCallbackInfo &info_; + const v8::Local data_; + + public: + explicit inline PropertyCallbackInfo( + const v8::PropertyCallbackInfo &info + , const v8::Local data) : + info_(info) + , data_(data) {} + + inline v8::Isolate* GetIsolate() const { return info_.GetIsolate(); } + inline v8::Local Data() const { return data_; } + inline v8::Local This() const { return info_.This(); } + inline v8::Local Holder() const { return info_.Holder(); } + inline ReturnValue GetReturnValue() const { + return ReturnValue(info_.GetReturnValue()); + } + + protected: + static const int kHolderIndex = 0; + static const int kIsolateIndex = 1; + static const int kReturnValueDefaultValueIndex = 2; + static const int kReturnValueIndex = 3; + static const int kDataIndex = 4; + static const int kThisIndex = 5; + static const int kArgsLength = 6; + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(PropertyCallbackInfo) +}; + +namespace imp { +static +void FunctionCallbackWrapper(const v8::FunctionCallbackInfo &info) { + v8::Local obj = info.Data().As(); + FunctionCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kFunctionIndex).As()->Value())); + FunctionCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + callback(cbinfo); +} + +typedef void (*NativeFunction)(const v8::FunctionCallbackInfo &); + +#if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION +static +void GetterCallbackWrapper( + v8::Local property + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + GetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kGetterIndex).As()->Value())); + callback(property.As(), cbinfo); +} + +typedef void (*NativeGetter) + (v8::Local, const v8::PropertyCallbackInfo &); + +static +void SetterCallbackWrapper( + v8::Local property + , v8::Local value + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + SetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kSetterIndex).As()->Value())); + callback(property.As(), value, cbinfo); +} + +typedef void (*NativeSetter)( + v8::Local + , v8::Local + , const v8::PropertyCallbackInfo &); +#else +static +void GetterCallbackWrapper( + v8::Local property + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + GetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kGetterIndex).As()->Value())); + callback(property, cbinfo); +} + +typedef void (*NativeGetter) + (v8::Local, const v8::PropertyCallbackInfo &); + +static +void SetterCallbackWrapper( + v8::Local property + , v8::Local value + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + SetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kSetterIndex).As()->Value())); + callback(property, value, cbinfo); +} + +typedef void (*NativeSetter)( + v8::Local + , v8::Local + , const v8::PropertyCallbackInfo &); +#endif + +#if NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION +static +void PropertyGetterCallbackWrapper( + v8::Local property + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyGetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyGetterIndex) + .As()->Value())); + callback(property.As(), cbinfo); +} + +typedef void (*NativePropertyGetter) + (v8::Local, const v8::PropertyCallbackInfo &); + +static +void PropertySetterCallbackWrapper( + v8::Local property + , v8::Local value + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertySetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertySetterIndex) + .As()->Value())); + callback(property.As(), value, cbinfo); +} + +typedef void (*NativePropertySetter)( + v8::Local + , v8::Local + , const v8::PropertyCallbackInfo &); + +static +void PropertyEnumeratorCallbackWrapper( + const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyEnumeratorCallback callback = + reinterpret_cast(reinterpret_cast( + obj->GetInternalField(kPropertyEnumeratorIndex) + .As()->Value())); + callback(cbinfo); +} + +typedef void (*NativePropertyEnumerator) + (const v8::PropertyCallbackInfo &); + +static +void PropertyDeleterCallbackWrapper( + v8::Local property + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyDeleterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyDeleterIndex) + .As()->Value())); + callback(property.As(), cbinfo); +} + +typedef void (NativePropertyDeleter) + (v8::Local, const v8::PropertyCallbackInfo &); + +static +void PropertyQueryCallbackWrapper( + v8::Local property + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyQueryCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyQueryIndex) + .As()->Value())); + callback(property.As(), cbinfo); +} + +typedef void (*NativePropertyQuery) + (v8::Local, const v8::PropertyCallbackInfo &); +#else +static +void PropertyGetterCallbackWrapper( + v8::Local property + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyGetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyGetterIndex) + .As()->Value())); + callback(property, cbinfo); +} + +typedef void (*NativePropertyGetter) + (v8::Local, const v8::PropertyCallbackInfo &); + +static +void PropertySetterCallbackWrapper( + v8::Local property + , v8::Local value + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertySetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertySetterIndex) + .As()->Value())); + callback(property, value, cbinfo); +} + +typedef void (*NativePropertySetter)( + v8::Local + , v8::Local + , const v8::PropertyCallbackInfo &); + +static +void PropertyEnumeratorCallbackWrapper( + const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyEnumeratorCallback callback = + reinterpret_cast(reinterpret_cast( + obj->GetInternalField(kPropertyEnumeratorIndex) + .As()->Value())); + callback(cbinfo); +} + +typedef void (*NativePropertyEnumerator) + (const v8::PropertyCallbackInfo &); + +static +void PropertyDeleterCallbackWrapper( + v8::Local property + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyDeleterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyDeleterIndex) + .As()->Value())); + callback(property, cbinfo); +} + +typedef void (NativePropertyDeleter) + (v8::Local, const v8::PropertyCallbackInfo &); + +static +void PropertyQueryCallbackWrapper( + v8::Local property + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyQueryCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyQueryIndex) + .As()->Value())); + callback(property, cbinfo); +} + +typedef void (*NativePropertyQuery) + (v8::Local, const v8::PropertyCallbackInfo &); +#endif + +static +void IndexGetterCallbackWrapper( + uint32_t index, const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexGetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertyGetterIndex) + .As()->Value())); + callback(index, cbinfo); +} + +typedef void (*NativeIndexGetter) + (uint32_t, const v8::PropertyCallbackInfo &); + +static +void IndexSetterCallbackWrapper( + uint32_t index + , v8::Local value + , const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexSetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertySetterIndex) + .As()->Value())); + callback(index, value, cbinfo); +} + +typedef void (*NativeIndexSetter)( + uint32_t + , v8::Local + , const v8::PropertyCallbackInfo &); + +static +void IndexEnumeratorCallbackWrapper( + const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexEnumeratorCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField( + kIndexPropertyEnumeratorIndex).As()->Value())); + callback(cbinfo); +} + +typedef void (*NativeIndexEnumerator) + (const v8::PropertyCallbackInfo &); + +static +void IndexDeleterCallbackWrapper( + uint32_t index, const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexDeleterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertyDeleterIndex) + .As()->Value())); + callback(index, cbinfo); +} + +typedef void (*NativeIndexDeleter) + (uint32_t, const v8::PropertyCallbackInfo &); + +static +void IndexQueryCallbackWrapper( + uint32_t index, const v8::PropertyCallbackInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexQueryCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertyQueryIndex) + .As()->Value())); + callback(index, cbinfo); +} + +typedef void (*NativeIndexQuery) + (uint32_t, const v8::PropertyCallbackInfo &); +} // end of namespace imp + +#endif // NAN_CALLBACKS_12_INL_H_ diff --git a/express-server/node_modules/nan/nan_callbacks_pre_12_inl.h b/express-server/node_modules/nan/nan_callbacks_pre_12_inl.h new file mode 100644 index 00000000..c9ba4993 --- /dev/null +++ b/express-server/node_modules/nan/nan_callbacks_pre_12_inl.h @@ -0,0 +1,520 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_CALLBACKS_PRE_12_INL_H_ +#define NAN_CALLBACKS_PRE_12_INL_H_ + +namespace imp { +template class ReturnValueImp; +} // end of namespace imp + +template +class ReturnValue { + v8::Isolate *isolate_; + v8::Persistent *value_; + friend class imp::ReturnValueImp; + + public: + template + explicit inline ReturnValue(v8::Isolate *isolate, v8::Persistent *p) : + isolate_(isolate), value_(p) {} + template + explicit inline ReturnValue(const ReturnValue& that) + : isolate_(that.isolate_), value_(that.value_) { + TYPE_CHECK(T, S); + } + + // Handle setters + template inline void Set(const v8::Local &handle) { + TYPE_CHECK(T, S); + value_->Dispose(); + *value_ = v8::Persistent::New(handle); + } + + template inline void Set(const Global &handle) { + TYPE_CHECK(T, S); + value_->Dispose(); + *value_ = v8::Persistent::New(handle.persistent); + const_cast &>(handle).Reset(); + } + + // Fast primitive setters + inline void Set(bool value) { + v8::HandleScope scope; + + TYPE_CHECK(T, v8::Boolean); + value_->Dispose(); + *value_ = v8::Persistent::New(v8::Boolean::New(value)); + } + + inline void Set(double i) { + v8::HandleScope scope; + + TYPE_CHECK(T, v8::Number); + value_->Dispose(); + *value_ = v8::Persistent::New(v8::Number::New(i)); + } + + inline void Set(int32_t i) { + v8::HandleScope scope; + + TYPE_CHECK(T, v8::Integer); + value_->Dispose(); + *value_ = v8::Persistent::New(v8::Int32::New(i)); + } + + inline void Set(uint32_t i) { + v8::HandleScope scope; + + TYPE_CHECK(T, v8::Integer); + value_->Dispose(); + *value_ = v8::Persistent::New(v8::Uint32::NewFromUnsigned(i)); + } + + // Fast JS primitive setters + inline void SetNull() { + v8::HandleScope scope; + + TYPE_CHECK(T, v8::Primitive); + value_->Dispose(); + *value_ = v8::Persistent::New(v8::Null()); + } + + inline void SetUndefined() { + v8::HandleScope scope; + + TYPE_CHECK(T, v8::Primitive); + value_->Dispose(); + *value_ = v8::Persistent::New(v8::Undefined()); + } + + inline void SetEmptyString() { + v8::HandleScope scope; + + TYPE_CHECK(T, v8::String); + value_->Dispose(); + *value_ = v8::Persistent::New(v8::String::Empty()); + } + + // Convenience getter for isolate + inline v8::Isolate *GetIsolate() const { + return isolate_; + } + + // Pointer setter: Uncompilable to prevent inadvertent misuse. + template + inline void Set(S *whatever) { TYPE_CHECK(S*, v8::Primitive); } +}; + +template +class FunctionCallbackInfo { + const v8::Arguments &args_; + v8::Local data_; + ReturnValue return_value_; + v8::Persistent retval_; + + public: + explicit inline FunctionCallbackInfo( + const v8::Arguments &args + , v8::Local data) : + args_(args) + , data_(data) + , return_value_(args.GetIsolate(), &retval_) + , retval_(v8::Persistent::New(v8::Undefined())) {} + + inline ~FunctionCallbackInfo() { + retval_.Dispose(); + retval_.Clear(); + } + + inline ReturnValue GetReturnValue() const { + return ReturnValue(return_value_); + } + + inline v8::Local Callee() const { return args_.Callee(); } + inline v8::Local Data() const { return data_; } + inline v8::Local Holder() const { return args_.Holder(); } + inline bool IsConstructCall() const { return args_.IsConstructCall(); } + inline int Length() const { return args_.Length(); } + inline v8::Local operator[](int i) const { return args_[i]; } + inline v8::Local This() const { return args_.This(); } + inline v8::Isolate *GetIsolate() const { return args_.GetIsolate(); } + + + protected: + static const int kHolderIndex = 0; + static const int kIsolateIndex = 1; + static const int kReturnValueDefaultValueIndex = 2; + static const int kReturnValueIndex = 3; + static const int kDataIndex = 4; + static const int kCalleeIndex = 5; + static const int kContextSaveIndex = 6; + static const int kArgsLength = 7; + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(FunctionCallbackInfo) +}; + +template +class PropertyCallbackInfoBase { + const v8::AccessorInfo &info_; + const v8::Local data_; + + public: + explicit inline PropertyCallbackInfoBase( + const v8::AccessorInfo &info + , const v8::Local data) : + info_(info) + , data_(data) {} + + inline v8::Isolate* GetIsolate() const { return info_.GetIsolate(); } + inline v8::Local Data() const { return data_; } + inline v8::Local This() const { return info_.This(); } + inline v8::Local Holder() const { return info_.Holder(); } + + protected: + static const int kHolderIndex = 0; + static const int kIsolateIndex = 1; + static const int kReturnValueDefaultValueIndex = 2; + static const int kReturnValueIndex = 3; + static const int kDataIndex = 4; + static const int kThisIndex = 5; + static const int kArgsLength = 6; + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(PropertyCallbackInfoBase) +}; + +template +class PropertyCallbackInfo : public PropertyCallbackInfoBase { + ReturnValue return_value_; + v8::Persistent retval_; + + public: + explicit inline PropertyCallbackInfo( + const v8::AccessorInfo &info + , const v8::Local data) : + PropertyCallbackInfoBase(info, data) + , return_value_(info.GetIsolate(), &retval_) + , retval_(v8::Persistent::New(v8::Undefined())) {} + + inline ~PropertyCallbackInfo() { + retval_.Dispose(); + retval_.Clear(); + } + + inline ReturnValue GetReturnValue() const { return return_value_; } +}; + +template<> +class PropertyCallbackInfo : + public PropertyCallbackInfoBase { + ReturnValue return_value_; + v8::Persistent retval_; + + public: + explicit inline PropertyCallbackInfo( + const v8::AccessorInfo &info + , const v8::Local data) : + PropertyCallbackInfoBase(info, data) + , return_value_(info.GetIsolate(), &retval_) + , retval_(v8::Persistent::New(v8::Local())) {} + + inline ~PropertyCallbackInfo() { + retval_.Dispose(); + retval_.Clear(); + } + + inline ReturnValue GetReturnValue() const { + return return_value_; + } +}; + +template<> +class PropertyCallbackInfo : + public PropertyCallbackInfoBase { + ReturnValue return_value_; + v8::Persistent retval_; + + public: + explicit inline PropertyCallbackInfo( + const v8::AccessorInfo &info + , const v8::Local data) : + PropertyCallbackInfoBase(info, data) + , return_value_(info.GetIsolate(), &retval_) + , retval_(v8::Persistent::New(v8::Local())) {} + + inline ~PropertyCallbackInfo() { + retval_.Dispose(); + retval_.Clear(); + } + + inline ReturnValue GetReturnValue() const { + return return_value_; + } +}; + +template<> +class PropertyCallbackInfo : + public PropertyCallbackInfoBase { + ReturnValue return_value_; + v8::Persistent retval_; + + public: + explicit inline PropertyCallbackInfo( + const v8::AccessorInfo &info + , const v8::Local data) : + PropertyCallbackInfoBase(info, data) + , return_value_(info.GetIsolate(), &retval_) + , retval_(v8::Persistent::New(v8::Local())) {} + + inline ~PropertyCallbackInfo() { + retval_.Dispose(); + retval_.Clear(); + } + + inline ReturnValue GetReturnValue() const { + return return_value_; + } +}; + +namespace imp { +template +class ReturnValueImp : public ReturnValue { + public: + explicit ReturnValueImp(ReturnValue that) : + ReturnValue(that) {} + inline v8::Handle Value() { + return *ReturnValue::value_; + } +}; + +static +v8::Handle FunctionCallbackWrapper(const v8::Arguments &args) { + v8::Local obj = args.Data().As(); + FunctionCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kFunctionIndex).As()->Value())); + FunctionCallbackInfo + cbinfo(args, obj->GetInternalField(kDataIndex)); + callback(cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativeFunction)(const v8::Arguments &); + +static +v8::Handle GetterCallbackWrapper( + v8::Local property, const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + GetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kGetterIndex).As()->Value())); + callback(property, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativeGetter) + (v8::Local, const v8::AccessorInfo &); + +static +void SetterCallbackWrapper( + v8::Local property + , v8::Local value + , const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + SetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kSetterIndex).As()->Value())); + callback(property, value, cbinfo); +} + +typedef void (*NativeSetter) + (v8::Local, v8::Local, const v8::AccessorInfo &); + +static +v8::Handle PropertyGetterCallbackWrapper( + v8::Local property, const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyGetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyGetterIndex) + .As()->Value())); + callback(property, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativePropertyGetter) + (v8::Local, const v8::AccessorInfo &); + +static +v8::Handle PropertySetterCallbackWrapper( + v8::Local property + , v8::Local value + , const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertySetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertySetterIndex) + .As()->Value())); + callback(property, value, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativePropertySetter) + (v8::Local, v8::Local, const v8::AccessorInfo &); + +static +v8::Handle PropertyEnumeratorCallbackWrapper( + const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyEnumeratorCallback callback = + reinterpret_cast(reinterpret_cast( + obj->GetInternalField(kPropertyEnumeratorIndex) + .As()->Value())); + callback(cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativePropertyEnumerator) + (const v8::AccessorInfo &); + +static +v8::Handle PropertyDeleterCallbackWrapper( + v8::Local property + , const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyDeleterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyDeleterIndex) + .As()->Value())); + callback(property, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (NativePropertyDeleter) + (v8::Local, const v8::AccessorInfo &); + +static +v8::Handle PropertyQueryCallbackWrapper( + v8::Local property, const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + PropertyQueryCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kPropertyQueryIndex) + .As()->Value())); + callback(property, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativePropertyQuery) + (v8::Local, const v8::AccessorInfo &); + +static +v8::Handle IndexGetterCallbackWrapper( + uint32_t index, const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexGetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertyGetterIndex) + .As()->Value())); + callback(index, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativeIndexGetter) + (uint32_t, const v8::AccessorInfo &); + +static +v8::Handle IndexSetterCallbackWrapper( + uint32_t index + , v8::Local value + , const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexSetterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertySetterIndex) + .As()->Value())); + callback(index, value, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativeIndexSetter) + (uint32_t, v8::Local, const v8::AccessorInfo &); + +static +v8::Handle IndexEnumeratorCallbackWrapper( + const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexEnumeratorCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertyEnumeratorIndex) + .As()->Value())); + callback(cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativeIndexEnumerator) + (const v8::AccessorInfo &); + +static +v8::Handle IndexDeleterCallbackWrapper( + uint32_t index, const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexDeleterCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertyDeleterIndex) + .As()->Value())); + callback(index, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativeIndexDeleter) + (uint32_t, const v8::AccessorInfo &); + +static +v8::Handle IndexQueryCallbackWrapper( + uint32_t index, const v8::AccessorInfo &info) { + v8::Local obj = info.Data().As(); + PropertyCallbackInfo + cbinfo(info, obj->GetInternalField(kDataIndex)); + IndexQueryCallback callback = reinterpret_cast( + reinterpret_cast( + obj->GetInternalField(kIndexPropertyQueryIndex) + .As()->Value())); + callback(index, cbinfo); + return ReturnValueImp(cbinfo.GetReturnValue()).Value(); +} + +typedef v8::Handle (*NativeIndexQuery) + (uint32_t, const v8::AccessorInfo &); +} // end of namespace imp + +#endif // NAN_CALLBACKS_PRE_12_INL_H_ diff --git a/express-server/node_modules/nan/nan_converters.h b/express-server/node_modules/nan/nan_converters.h new file mode 100644 index 00000000..c0b32729 --- /dev/null +++ b/express-server/node_modules/nan/nan_converters.h @@ -0,0 +1,72 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_CONVERTERS_H_ +#define NAN_CONVERTERS_H_ + +namespace imp { +template struct ToFactoryBase { + typedef MaybeLocal return_t; +}; +template struct ValueFactoryBase { typedef Maybe return_t; }; + +template struct ToFactory; + +template<> +struct ToFactory : ToFactoryBase { + static inline return_t convert(v8::Local val) { + if (val.IsEmpty() || !val->IsFunction()) return MaybeLocal(); + return MaybeLocal(val.As()); + } +}; + +#define X(TYPE) \ + template<> \ + struct ToFactory : ToFactoryBase { \ + static inline return_t convert(v8::Local val); \ + }; + +X(Boolean) +X(Number) +X(String) +X(Object) +X(Integer) +X(Uint32) +X(Int32) + +#undef X + +#define X(TYPE) \ + template<> \ + struct ToFactory : ValueFactoryBase { \ + static inline return_t convert(v8::Local val); \ + }; + +X(bool) +X(double) +X(int64_t) +X(uint32_t) +X(int32_t) + +#undef X +} // end of namespace imp + +template +inline +typename imp::ToFactory::return_t To(v8::Local val) { + return imp::ToFactory::convert(val); +} + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +# include "nan_converters_43_inl.h" +#else +# include "nan_converters_pre_43_inl.h" +#endif + +#endif // NAN_CONVERTERS_H_ diff --git a/express-server/node_modules/nan/nan_converters_43_inl.h b/express-server/node_modules/nan/nan_converters_43_inl.h new file mode 100644 index 00000000..742f5432 --- /dev/null +++ b/express-server/node_modules/nan/nan_converters_43_inl.h @@ -0,0 +1,48 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_CONVERTERS_43_INL_H_ +#define NAN_CONVERTERS_43_INL_H_ + +#define X(TYPE) \ +imp::ToFactory::return_t \ +imp::ToFactory::convert(v8::Local val) { \ + v8::Isolate *isolate = v8::Isolate::GetCurrent(); \ + v8::EscapableHandleScope scope(isolate); \ + return scope.Escape( \ + val->To ## TYPE(isolate->GetCurrentContext()) \ + .FromMaybe(v8::Local())); \ +} + +X(Boolean) +X(Number) +X(String) +X(Object) +X(Integer) +X(Uint32) +X(Int32) + +#undef X + +#define X(TYPE, NAME) \ +imp::ToFactory::return_t \ +imp::ToFactory::convert(v8::Local val) { \ + v8::Isolate *isolate = v8::Isolate::GetCurrent(); \ + v8::HandleScope scope(isolate); \ + return val->NAME ## Value(isolate->GetCurrentContext()); \ +} + +X(bool, Boolean) +X(double, Number) +X(int64_t, Integer) +X(uint32_t, Uint32) +X(int32_t, Int32) + +#undef X + +#endif // NAN_CONVERTERS_43_INL_H_ diff --git a/express-server/node_modules/nan/nan_converters_pre_43_inl.h b/express-server/node_modules/nan/nan_converters_pre_43_inl.h new file mode 100644 index 00000000..ae0518aa --- /dev/null +++ b/express-server/node_modules/nan/nan_converters_pre_43_inl.h @@ -0,0 +1,42 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_CONVERTERS_PRE_43_INL_H_ +#define NAN_CONVERTERS_PRE_43_INL_H_ + +#define X(TYPE) \ +imp::ToFactory::return_t \ +imp::ToFactory::convert(v8::Local val) { \ + return val->To ## TYPE(); \ +} + +X(Boolean) +X(Number) +X(String) +X(Object) +X(Integer) +X(Uint32) +X(Int32) + +#undef X + +#define X(TYPE, NAME) \ +imp::ToFactory::return_t \ +imp::ToFactory::convert(v8::Local val) { \ + return Just(val->NAME ## Value()); \ +} + +X(bool, Boolean) +X(double, Number) +X(int64_t, Integer) +X(uint32_t, Uint32) +X(int32_t, Int32) + +#undef X + +#endif // NAN_CONVERTERS_PRE_43_INL_H_ diff --git a/express-server/node_modules/nan/nan_define_own_property_helper.h b/express-server/node_modules/nan/nan_define_own_property_helper.h new file mode 100644 index 00000000..d710ef22 --- /dev/null +++ b/express-server/node_modules/nan/nan_define_own_property_helper.h @@ -0,0 +1,29 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_DEFINE_OWN_PROPERTY_HELPER_H_ +#define NAN_DEFINE_OWN_PROPERTY_HELPER_H_ + +namespace imp { + +inline Maybe DefineOwnPropertyHelper( + v8::PropertyAttribute current + , v8::Handle obj + , v8::Handle key + , v8::Handle value + , v8::PropertyAttribute attribs = v8::None) { + return !(current & v8::DontDelete) || // configurable OR + (!(current & v8::ReadOnly) && // writable AND + !((attribs ^ current) & ~v8::ReadOnly)) // same excluding RO + ? Just(obj->ForceSet(key, value, attribs)) + : Nothing(); +} + +} // end of namespace imp + +#endif // NAN_DEFINE_OWN_PROPERTY_HELPER_H_ diff --git a/express-server/node_modules/nan/nan_implementation_12_inl.h b/express-server/node_modules/nan/nan_implementation_12_inl.h new file mode 100644 index 00000000..6d68ed50 --- /dev/null +++ b/express-server/node_modules/nan/nan_implementation_12_inl.h @@ -0,0 +1,424 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_IMPLEMENTATION_12_INL_H_ +#define NAN_IMPLEMENTATION_12_INL_H_ +//============================================================================== +// node v0.11 implementation +//============================================================================== + +namespace imp { + +//=== Array ==================================================================== + +Factory::return_t +Factory::New() { + return v8::Array::New(v8::Isolate::GetCurrent()); +} + +Factory::return_t +Factory::New(int length) { + return v8::Array::New(v8::Isolate::GetCurrent(), length); +} + +//=== Boolean ================================================================== + +Factory::return_t +Factory::New(bool value) { + return v8::Boolean::New(v8::Isolate::GetCurrent(), value); +} + +//=== Boolean Object =========================================================== + +Factory::return_t +Factory::New(bool value) { +#if (NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION) + return v8::BooleanObject::New( + v8::Isolate::GetCurrent(), value).As(); +#else + return v8::BooleanObject::New(value).As(); +#endif +} + +//=== Context ================================================================== + +Factory::return_t +Factory::New( v8::ExtensionConfiguration* extensions + , v8::Local tmpl + , v8::Local obj) { + return v8::Context::New(v8::Isolate::GetCurrent(), extensions, tmpl, obj); +} + +//=== Date ===================================================================== + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +Factory::return_t +Factory::New(double value) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(v8::Date::New(isolate->GetCurrentContext(), value) + .FromMaybe(v8::Local()).As()); +} +#else +Factory::return_t +Factory::New(double value) { + return v8::Date::New(v8::Isolate::GetCurrent(), value).As(); +} +#endif + +//=== External ================================================================= + +Factory::return_t +Factory::New(void * value) { + return v8::External::New(v8::Isolate::GetCurrent(), value); +} + +//=== Function ================================================================= + +Factory::return_t +Factory::New( FunctionCallback callback + , v8::Local data) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + v8::Local tpl = v8::ObjectTemplate::New(isolate); + tpl->SetInternalFieldCount(imp::kFunctionFieldCount); + v8::Local obj = NewInstance(tpl).ToLocalChecked(); + + obj->SetInternalField( + imp::kFunctionIndex + , v8::External::New(isolate, reinterpret_cast(callback))); + + v8::Local val = v8::Local::New(isolate, data); + + if (!val.IsEmpty()) { + obj->SetInternalField(imp::kDataIndex, val); + } + +#if NODE_MAJOR_VERSION >= 10 + v8::Local context = isolate->GetCurrentContext(); + v8::Local function = + v8::Function::New(context, imp::FunctionCallbackWrapper, obj) + .ToLocalChecked(); +#else + v8::Local function = + v8::Function::New(isolate, imp::FunctionCallbackWrapper, obj); +#endif + + return scope.Escape(function); +} + +//=== Function Template ======================================================== + +Factory::return_t +Factory::New( FunctionCallback callback + , v8::Local data + , v8::Local signature) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + if (callback) { + v8::EscapableHandleScope scope(isolate); + v8::Local tpl = v8::ObjectTemplate::New(isolate); + tpl->SetInternalFieldCount(imp::kFunctionFieldCount); + v8::Local obj = NewInstance(tpl).ToLocalChecked(); + + obj->SetInternalField( + imp::kFunctionIndex + , v8::External::New(isolate, reinterpret_cast(callback))); + v8::Local val = v8::Local::New(isolate, data); + + if (!val.IsEmpty()) { + obj->SetInternalField(imp::kDataIndex, val); + } + + return scope.Escape(v8::FunctionTemplate::New( isolate + , imp::FunctionCallbackWrapper + , obj + , signature)); + } else { + return v8::FunctionTemplate::New(isolate, 0, data, signature); + } +} + +//=== Number =================================================================== + +Factory::return_t +Factory::New(double value) { + return v8::Number::New(v8::Isolate::GetCurrent(), value); +} + +//=== Number Object ============================================================ + +Factory::return_t +Factory::New(double value) { + return v8::NumberObject::New( v8::Isolate::GetCurrent() + , value).As(); +} + +//=== Integer, Int32 and Uint32 ================================================ + +template +typename IntegerFactory::return_t +IntegerFactory::New(int32_t value) { + return To(T::New(v8::Isolate::GetCurrent(), value)); +} + +template +typename IntegerFactory::return_t +IntegerFactory::New(uint32_t value) { + return To(T::NewFromUnsigned(v8::Isolate::GetCurrent(), value)); +} + +Factory::return_t +Factory::New(int32_t value) { + return To( + v8::Uint32::NewFromUnsigned(v8::Isolate::GetCurrent(), value)); +} + +Factory::return_t +Factory::New(uint32_t value) { + return To( + v8::Uint32::NewFromUnsigned(v8::Isolate::GetCurrent(), value)); +} + +//=== Object =================================================================== + +Factory::return_t +Factory::New() { + return v8::Object::New(v8::Isolate::GetCurrent()); +} + +//=== Object Template ========================================================== + +Factory::return_t +Factory::New() { + return v8::ObjectTemplate::New(v8::Isolate::GetCurrent()); +} + +//=== RegExp =================================================================== + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +Factory::return_t +Factory::New( + v8::Local pattern + , v8::RegExp::Flags flags) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape( + v8::RegExp::New(isolate->GetCurrentContext(), pattern, flags) + .FromMaybe(v8::Local())); +} +#else +Factory::return_t +Factory::New( + v8::Local pattern + , v8::RegExp::Flags flags) { + return v8::RegExp::New(pattern, flags); +} +#endif + +//=== Script =================================================================== + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +Factory::return_t +Factory::New( v8::Local source) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + v8::ScriptCompiler::Source src(source); + return scope.Escape( + v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &src) + .FromMaybe(v8::Local())); +} + +Factory::return_t +Factory::New( v8::Local source + , v8::ScriptOrigin const& origin) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + v8::ScriptCompiler::Source src(source, origin); + return scope.Escape( + v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &src) + .FromMaybe(v8::Local())); +} +#else +Factory::return_t +Factory::New( v8::Local source) { + v8::ScriptCompiler::Source src(source); + return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &src); +} + +Factory::return_t +Factory::New( v8::Local source + , v8::ScriptOrigin const& origin) { + v8::ScriptCompiler::Source src(source, origin); + return v8::ScriptCompiler::Compile(v8::Isolate::GetCurrent(), &src); +} +#endif + +//=== Signature ================================================================ + +Factory::return_t +Factory::New(Factory::FTH receiver) { + return v8::Signature::New(v8::Isolate::GetCurrent(), receiver); +} + +//=== String =================================================================== + +Factory::return_t +Factory::New() { + return v8::String::Empty(v8::Isolate::GetCurrent()); +} + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +Factory::return_t +Factory::New(const char * value, int length) { + return v8::String::NewFromUtf8( + v8::Isolate::GetCurrent(), value, v8::NewStringType::kNormal, length); +} + +Factory::return_t +Factory::New(std::string const& value) { + assert(value.size() <= INT_MAX && "string too long"); + return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), + value.data(), v8::NewStringType::kNormal, static_cast(value.size())); +} + +Factory::return_t +Factory::New(const uint16_t * value, int length) { + return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), value, + v8::NewStringType::kNormal, length); +} + +Factory::return_t +Factory::New(v8::String::ExternalStringResource * value) { + return v8::String::NewExternalTwoByte(v8::Isolate::GetCurrent(), value); +} + +Factory::return_t +Factory::New(ExternalOneByteStringResource * value) { + return v8::String::NewExternalOneByte(v8::Isolate::GetCurrent(), value); +} +#else +Factory::return_t +Factory::New(const char * value, int length) { + return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), value, + v8::String::kNormalString, length); +} + +Factory::return_t +Factory::New( + std::string const& value) /* NOLINT(build/include_what_you_use) */ { + assert(value.size() <= INT_MAX && "string too long"); + return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), value.data(), + v8::String::kNormalString, + static_cast(value.size())); +} + +Factory::return_t +Factory::New(const uint16_t * value, int length) { + return v8::String::NewFromTwoByte(v8::Isolate::GetCurrent(), value, + v8::String::kNormalString, length); +} + +Factory::return_t +Factory::New(v8::String::ExternalStringResource * value) { + return v8::String::NewExternal(v8::Isolate::GetCurrent(), value); +} + +Factory::return_t +Factory::New(ExternalOneByteStringResource * value) { + return v8::String::NewExternal(v8::Isolate::GetCurrent(), value); +} +#endif + +//=== String Object ============================================================ + +// See https://github.com/nodejs/nan/pull/811#discussion_r224594980. +// Disable the warning as there is no way around it. +// TODO(bnoordhuis) Use isolate-based version in Node.js v12. +Factory::return_t +Factory::New(v8::Local value) { +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4996) +#endif +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + return v8::StringObject::New(value).As(); +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif +#ifdef _MSC_VER +#pragma warning(pop) +#endif +} + +//=== Unbound Script =========================================================== + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +Factory::return_t +Factory::New(v8::Local source) { + v8::ScriptCompiler::Source src(source); + return v8::ScriptCompiler::CompileUnboundScript( + v8::Isolate::GetCurrent(), &src); +} + +Factory::return_t +Factory::New( v8::Local source + , v8::ScriptOrigin const& origin) { + v8::ScriptCompiler::Source src(source, origin); + return v8::ScriptCompiler::CompileUnboundScript( + v8::Isolate::GetCurrent(), &src); +} +#else +Factory::return_t +Factory::New(v8::Local source) { + v8::ScriptCompiler::Source src(source); + return v8::ScriptCompiler::CompileUnbound(v8::Isolate::GetCurrent(), &src); +} + +Factory::return_t +Factory::New( v8::Local source + , v8::ScriptOrigin const& origin) { + v8::ScriptCompiler::Source src(source, origin); + return v8::ScriptCompiler::CompileUnbound(v8::Isolate::GetCurrent(), &src); +} +#endif + +} // end of namespace imp + +//=== Presistents and Handles ================================================== + +#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION +template +inline v8::Local New(v8::Handle h) { + return v8::Local::New(v8::Isolate::GetCurrent(), h); +} +#endif + +template +inline v8::Local New(v8::Persistent const& p) { + return v8::Local::New(v8::Isolate::GetCurrent(), p); +} + +template +inline v8::Local New(Persistent const& p) { + return v8::Local::New(v8::Isolate::GetCurrent(), p); +} + +template +inline v8::Local New(Global const& p) { + return v8::Local::New(v8::Isolate::GetCurrent(), p); +} + +#endif // NAN_IMPLEMENTATION_12_INL_H_ diff --git a/express-server/node_modules/nan/nan_implementation_pre_12_inl.h b/express-server/node_modules/nan/nan_implementation_pre_12_inl.h new file mode 100644 index 00000000..1472421a --- /dev/null +++ b/express-server/node_modules/nan/nan_implementation_pre_12_inl.h @@ -0,0 +1,263 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_IMPLEMENTATION_PRE_12_INL_H_ +#define NAN_IMPLEMENTATION_PRE_12_INL_H_ + +//============================================================================== +// node v0.10 implementation +//============================================================================== + +namespace imp { + +//=== Array ==================================================================== + +Factory::return_t +Factory::New() { + return v8::Array::New(); +} + +Factory::return_t +Factory::New(int length) { + return v8::Array::New(length); +} + +//=== Boolean ================================================================== + +Factory::return_t +Factory::New(bool value) { + return v8::Boolean::New(value)->ToBoolean(); +} + +//=== Boolean Object =========================================================== + +Factory::return_t +Factory::New(bool value) { + return v8::BooleanObject::New(value).As(); +} + +//=== Context ================================================================== + +Factory::return_t +Factory::New( v8::ExtensionConfiguration* extensions + , v8::Local tmpl + , v8::Local obj) { + v8::Persistent ctx = v8::Context::New(extensions, tmpl, obj); + v8::Local lctx = v8::Local::New(ctx); + ctx.Dispose(); + return lctx; +} + +//=== Date ===================================================================== + +Factory::return_t +Factory::New(double value) { + return v8::Date::New(value).As(); +} + +//=== External ================================================================= + +Factory::return_t +Factory::New(void * value) { + return v8::External::New(value); +} + +//=== Function ================================================================= + +Factory::return_t +Factory::New( FunctionCallback callback + , v8::Local data) { + v8::HandleScope scope; + + return scope.Close(Factory::New( + callback, data, v8::Local()) + ->GetFunction()); +} + + +//=== FunctionTemplate ========================================================= + +Factory::return_t +Factory::New( FunctionCallback callback + , v8::Local data + , v8::Local signature) { + if (callback) { + v8::HandleScope scope; + + v8::Local tpl = v8::ObjectTemplate::New(); + tpl->SetInternalFieldCount(imp::kFunctionFieldCount); + v8::Local obj = tpl->NewInstance(); + + obj->SetInternalField( + imp::kFunctionIndex + , v8::External::New(reinterpret_cast(callback))); + + v8::Local val = v8::Local::New(data); + + if (!val.IsEmpty()) { + obj->SetInternalField(imp::kDataIndex, val); + } + + // Note(agnat): Emulate length argument here. Unfortunately, I couldn't find + // a way. Have at it though... + return scope.Close( + v8::FunctionTemplate::New(imp::FunctionCallbackWrapper + , obj + , signature)); + } else { + return v8::FunctionTemplate::New(0, data, signature); + } +} + +//=== Number =================================================================== + +Factory::return_t +Factory::New(double value) { + return v8::Number::New(value); +} + +//=== Number Object ============================================================ + +Factory::return_t +Factory::New(double value) { + return v8::NumberObject::New(value).As(); +} + +//=== Integer, Int32 and Uint32 ================================================ + +template +typename IntegerFactory::return_t +IntegerFactory::New(int32_t value) { + return To(T::New(value)); +} + +template +typename IntegerFactory::return_t +IntegerFactory::New(uint32_t value) { + return To(T::NewFromUnsigned(value)); +} + +Factory::return_t +Factory::New(int32_t value) { + return To(v8::Uint32::NewFromUnsigned(value)); +} + +Factory::return_t +Factory::New(uint32_t value) { + return To(v8::Uint32::NewFromUnsigned(value)); +} + + +//=== Object =================================================================== + +Factory::return_t +Factory::New() { + return v8::Object::New(); +} + +//=== Object Template ========================================================== + +Factory::return_t +Factory::New() { + return v8::ObjectTemplate::New(); +} + +//=== RegExp =================================================================== + +Factory::return_t +Factory::New( + v8::Local pattern + , v8::RegExp::Flags flags) { + return v8::RegExp::New(pattern, flags); +} + +//=== Script =================================================================== + +Factory::return_t +Factory::New( v8::Local source) { + return v8::Script::New(source); +} +Factory::return_t +Factory::New( v8::Local source + , v8::ScriptOrigin const& origin) { + return v8::Script::New(source, const_cast(&origin)); +} + +//=== Signature ================================================================ + +Factory::return_t +Factory::New(Factory::FTH receiver) { + return v8::Signature::New(receiver); +} + +//=== String =================================================================== + +Factory::return_t +Factory::New() { + return v8::String::Empty(); +} + +Factory::return_t +Factory::New(const char * value, int length) { + return v8::String::New(value, length); +} + +Factory::return_t +Factory::New( + std::string const& value) /* NOLINT(build/include_what_you_use) */ { + assert(value.size() <= INT_MAX && "string too long"); + return v8::String::New(value.data(), static_cast(value.size())); +} + +Factory::return_t +Factory::New(const uint16_t * value, int length) { + return v8::String::New(value, length); +} + +Factory::return_t +Factory::New(v8::String::ExternalStringResource * value) { + return v8::String::NewExternal(value); +} + +Factory::return_t +Factory::New(v8::String::ExternalAsciiStringResource * value) { + return v8::String::NewExternal(value); +} + +//=== String Object ============================================================ + +Factory::return_t +Factory::New(v8::Local value) { + return v8::StringObject::New(value).As(); +} + +} // end of namespace imp + +//=== Presistents and Handles ================================================== + +template +inline v8::Local New(v8::Handle h) { + return v8::Local::New(h); +} + +template +inline v8::Local New(v8::Persistent const& p) { + return v8::Local::New(p); +} + +template +inline v8::Local New(Persistent const& p) { + return v8::Local::New(p.persistent); +} + +template +inline v8::Local New(Global const& p) { + return v8::Local::New(p.persistent); +} + +#endif // NAN_IMPLEMENTATION_PRE_12_INL_H_ diff --git a/express-server/node_modules/nan/nan_json.h b/express-server/node_modules/nan/nan_json.h new file mode 100644 index 00000000..33ac8ba6 --- /dev/null +++ b/express-server/node_modules/nan/nan_json.h @@ -0,0 +1,166 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_JSON_H_ +#define NAN_JSON_H_ + +#if NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION +#define NAN_JSON_H_NEED_PARSE 1 +#else +#define NAN_JSON_H_NEED_PARSE 0 +#endif // NODE_MODULE_VERSION < NODE_0_12_MODULE_VERSION + +#if NODE_MODULE_VERSION >= NODE_7_0_MODULE_VERSION +#define NAN_JSON_H_NEED_STRINGIFY 0 +#else +#define NAN_JSON_H_NEED_STRINGIFY 1 +#endif // NODE_MODULE_VERSION >= NODE_7_0_MODULE_VERSION + +class JSON { + public: + JSON() { +#if NAN_JSON_H_NEED_PARSE + NAN_JSON_H_NEED_STRINGIFY + Nan::HandleScope scope; + + Nan::MaybeLocal maybe_global_json = Nan::Get( + Nan::GetCurrentContext()->Global(), + Nan::New("JSON").ToLocalChecked() + ); + + assert(!maybe_global_json.IsEmpty() && "global JSON is empty"); + v8::Local val_global_json = maybe_global_json.ToLocalChecked(); + + assert(val_global_json->IsObject() && "global JSON is not an object"); + Nan::MaybeLocal maybe_obj_global_json = + Nan::To(val_global_json); + + assert(!maybe_obj_global_json.IsEmpty() && "global JSON object is empty"); + v8::Local global_json = maybe_obj_global_json.ToLocalChecked(); + +#if NAN_JSON_H_NEED_PARSE + Nan::MaybeLocal maybe_parse_method = Nan::Get( + global_json, Nan::New("parse").ToLocalChecked() + ); + + assert(!maybe_parse_method.IsEmpty() && "JSON.parse is empty"); + v8::Local parse_method = maybe_parse_method.ToLocalChecked(); + + assert(parse_method->IsFunction() && "JSON.parse is not a function"); + parse_cb_.Reset(parse_method.As()); +#endif // NAN_JSON_H_NEED_PARSE + +#if NAN_JSON_H_NEED_STRINGIFY + Nan::MaybeLocal maybe_stringify_method = Nan::Get( + global_json, Nan::New("stringify").ToLocalChecked() + ); + + assert(!maybe_stringify_method.IsEmpty() && "JSON.stringify is empty"); + v8::Local stringify_method = + maybe_stringify_method.ToLocalChecked(); + + assert( + stringify_method->IsFunction() && "JSON.stringify is not a function" + ); + stringify_cb_.Reset(stringify_method.As()); +#endif // NAN_JSON_H_NEED_STRINGIFY +#endif // NAN_JSON_H_NEED_PARSE + NAN_JSON_H_NEED_STRINGIFY + } + + inline + Nan::MaybeLocal Parse(v8::Local json_string) { + Nan::EscapableHandleScope scope; +#if NAN_JSON_H_NEED_PARSE + return scope.Escape(parse(json_string)); +#else + Nan::MaybeLocal result; +#if NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION && \ + NODE_MODULE_VERSION <= IOJS_2_0_MODULE_VERSION + result = v8::JSON::Parse(json_string); +#else +#if NODE_MODULE_VERSION > NODE_6_0_MODULE_VERSION + v8::Local context_or_isolate = Nan::GetCurrentContext(); +#else + v8::Isolate* context_or_isolate = v8::Isolate::GetCurrent(); +#endif // NODE_MODULE_VERSION > NODE_6_0_MODULE_VERSION + result = v8::JSON::Parse(context_or_isolate, json_string); +#endif // NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION && + // NODE_MODULE_VERSION <= IOJS_2_0_MODULE_VERSION + if (result.IsEmpty()) return v8::Local(); + return scope.Escape(result.ToLocalChecked()); +#endif // NAN_JSON_H_NEED_PARSE + } + + inline + Nan::MaybeLocal Stringify(v8::Local json_object) { + Nan::EscapableHandleScope scope; + Nan::MaybeLocal result = +#if NAN_JSON_H_NEED_STRINGIFY + Nan::To(stringify(json_object)); +#else + v8::JSON::Stringify(Nan::GetCurrentContext(), json_object); +#endif // NAN_JSON_H_NEED_STRINGIFY + if (result.IsEmpty()) return v8::Local(); + return scope.Escape(result.ToLocalChecked()); + } + + inline + Nan::MaybeLocal Stringify(v8::Local json_object, + v8::Local gap) { + Nan::EscapableHandleScope scope; + Nan::MaybeLocal result = +#if NAN_JSON_H_NEED_STRINGIFY + Nan::To(stringify(json_object, gap)); +#else + v8::JSON::Stringify(Nan::GetCurrentContext(), json_object, gap); +#endif // NAN_JSON_H_NEED_STRINGIFY + if (result.IsEmpty()) return v8::Local(); + return scope.Escape(result.ToLocalChecked()); + } + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(JSON) +#if NAN_JSON_H_NEED_PARSE + Nan::Callback parse_cb_; +#endif // NAN_JSON_H_NEED_PARSE +#if NAN_JSON_H_NEED_STRINGIFY + Nan::Callback stringify_cb_; +#endif // NAN_JSON_H_NEED_STRINGIFY + +#if NAN_JSON_H_NEED_PARSE + inline v8::Local parse(v8::Local arg) { + assert(!parse_cb_.IsEmpty() && "parse_cb_ is empty"); + AsyncResource resource("nan:JSON.parse"); + return parse_cb_.Call(1, &arg, &resource).FromMaybe(v8::Local()); + } +#endif // NAN_JSON_H_NEED_PARSE + +#if NAN_JSON_H_NEED_STRINGIFY + inline v8::Local stringify(v8::Local arg) { + assert(!stringify_cb_.IsEmpty() && "stringify_cb_ is empty"); + AsyncResource resource("nan:JSON.stringify"); + return stringify_cb_.Call(1, &arg, &resource) + .FromMaybe(v8::Local()); + } + + inline v8::Local stringify(v8::Local arg, + v8::Local gap) { + assert(!stringify_cb_.IsEmpty() && "stringify_cb_ is empty"); + + v8::Local argv[] = { + arg, + Nan::Null(), + gap + }; + AsyncResource resource("nan:JSON.stringify"); + return stringify_cb_.Call(3, argv, &resource) + .FromMaybe(v8::Local()); + } +#endif // NAN_JSON_H_NEED_STRINGIFY +}; + +#endif // NAN_JSON_H_ diff --git a/express-server/node_modules/nan/nan_maybe_43_inl.h b/express-server/node_modules/nan/nan_maybe_43_inl.h new file mode 100644 index 00000000..91783da6 --- /dev/null +++ b/express-server/node_modules/nan/nan_maybe_43_inl.h @@ -0,0 +1,369 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_MAYBE_43_INL_H_ +#define NAN_MAYBE_43_INL_H_ + +template +using MaybeLocal = v8::MaybeLocal; + +template +using Maybe = v8::Maybe; + +template +inline Maybe Nothing() { + return v8::Nothing(); +} + +template +inline Maybe Just(const T& t) { + return v8::Just(t); +} + +inline +MaybeLocal ToDetailString(v8::Local val) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(val->ToDetailString(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + +inline +MaybeLocal ToArrayIndex(v8::Local val) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(val->ToArrayIndex(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + +inline +Maybe Equals(v8::Local a, v8::Local(b)) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return a->Equals(isolate->GetCurrentContext(), b); +} + +inline +MaybeLocal NewInstance(v8::Local h) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(h->NewInstance(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + +inline +MaybeLocal NewInstance( + v8::Local h + , int argc + , v8::Local argv[]) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(h->NewInstance(isolate->GetCurrentContext(), argc, argv) + .FromMaybe(v8::Local())); +} + +inline +MaybeLocal NewInstance(v8::Local h) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(h->NewInstance(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + + +inline MaybeLocal GetFunction( + v8::Local t) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(t->GetFunction(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + +inline Maybe Set( + v8::Local obj + , v8::Local key + , v8::Local value) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->Set(isolate->GetCurrentContext(), key, value); +} + +inline Maybe Set( + v8::Local obj + , uint32_t index + , v8::Local value) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->Set(isolate->GetCurrentContext(), index, value); +} + +#if NODE_MODULE_VERSION < NODE_4_0_MODULE_VERSION +#include "nan_define_own_property_helper.h" // NOLINT(build/include) +#endif + +inline Maybe DefineOwnProperty( + v8::Local obj + , v8::Local key + , v8::Local value + , v8::PropertyAttribute attribs = v8::None) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); +#if NODE_MODULE_VERSION >= NODE_4_0_MODULE_VERSION + return obj->DefineOwnProperty(isolate->GetCurrentContext(), key, value, + attribs); +#else + Maybe maybeCurrent = + obj->GetPropertyAttributes(isolate->GetCurrentContext(), key); + if (maybeCurrent.IsNothing()) { + return Nothing(); + } + v8::PropertyAttribute current = maybeCurrent.FromJust(); + return imp::DefineOwnPropertyHelper(current, obj, key, value, attribs); +#endif +} + +NAN_DEPRECATED inline Maybe ForceSet( + v8::Local obj + , v8::Local key + , v8::Local value + , v8::PropertyAttribute attribs = v8::None) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); +#if NODE_MODULE_VERSION >= NODE_9_0_MODULE_VERSION + return key->IsName() + ? obj->DefineOwnProperty(isolate->GetCurrentContext(), + key.As(), value, attribs) + : Nothing(); +#else + return obj->ForceSet(isolate->GetCurrentContext(), key, value, attribs); +#endif +} + +inline MaybeLocal Get( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(obj->Get(isolate->GetCurrentContext(), key) + .FromMaybe(v8::Local())); +} + +inline +MaybeLocal Get(v8::Local obj, uint32_t index) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(obj->Get(isolate->GetCurrentContext(), index) + .FromMaybe(v8::Local())); +} + +inline v8::PropertyAttribute GetPropertyAttributes( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->GetPropertyAttributes(isolate->GetCurrentContext(), key) + .FromJust(); +} + +inline Maybe Has( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->Has(isolate->GetCurrentContext(), key); +} + +inline Maybe Has(v8::Local obj, uint32_t index) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->Has(isolate->GetCurrentContext(), index); +} + +inline Maybe Delete( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->Delete(isolate->GetCurrentContext(), key); +} + +inline +Maybe Delete(v8::Local obj, uint32_t index) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->Delete(isolate->GetCurrentContext(), index); +} + +inline +MaybeLocal GetPropertyNames(v8::Local obj) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(obj->GetPropertyNames(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + +inline +MaybeLocal GetOwnPropertyNames(v8::Local obj) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(obj->GetOwnPropertyNames(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + +inline Maybe SetPrototype( + v8::Local obj + , v8::Local prototype) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->SetPrototype(isolate->GetCurrentContext(), prototype); +} + +inline MaybeLocal ObjectProtoToString( + v8::Local obj) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(obj->ObjectProtoToString(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + +inline Maybe HasOwnProperty( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->HasOwnProperty(isolate->GetCurrentContext(), key); +} + +inline Maybe HasRealNamedProperty( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->HasRealNamedProperty(isolate->GetCurrentContext(), key); +} + +inline Maybe HasRealIndexedProperty( + v8::Local obj + , uint32_t index) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->HasRealIndexedProperty(isolate->GetCurrentContext(), index); +} + +inline Maybe HasRealNamedCallbackProperty( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return obj->HasRealNamedCallbackProperty(isolate->GetCurrentContext(), key); +} + +inline MaybeLocal GetRealNamedPropertyInPrototypeChain( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(obj->GetRealNamedPropertyInPrototypeChain( + isolate->GetCurrentContext(), key) + .FromMaybe(v8::Local())); +} + +inline MaybeLocal GetRealNamedProperty( + v8::Local obj + , v8::Local key) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape( + obj->GetRealNamedProperty(isolate->GetCurrentContext(), key) + .FromMaybe(v8::Local())); +} + +inline MaybeLocal CallAsFunction( + v8::Local obj + , v8::Local recv + , int argc + , v8::Local argv[]) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape( + obj->CallAsFunction(isolate->GetCurrentContext(), recv, argc, argv) + .FromMaybe(v8::Local())); +} + +inline MaybeLocal CallAsConstructor( + v8::Local obj + , int argc, v8::Local argv[]) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape( + obj->CallAsConstructor(isolate->GetCurrentContext(), argc, argv) + .FromMaybe(v8::Local())); +} + +inline +MaybeLocal GetSourceLine(v8::Local msg) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(msg->GetSourceLine(isolate->GetCurrentContext()) + .FromMaybe(v8::Local())); +} + +inline Maybe GetLineNumber(v8::Local msg) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return msg->GetLineNumber(isolate->GetCurrentContext()); +} + +inline Maybe GetStartColumn(v8::Local msg) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return msg->GetStartColumn(isolate->GetCurrentContext()); +} + +inline Maybe GetEndColumn(v8::Local msg) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + return msg->GetEndColumn(isolate->GetCurrentContext()); +} + +inline MaybeLocal CloneElementAt( + v8::Local array + , uint32_t index) { +#if (NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION) + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + v8::Local context = isolate->GetCurrentContext(); + v8::Local elem; + v8::Local obj; + if (!array->Get(context, index).ToLocal(&elem)) { + return scope.Escape(obj); + } + if (!elem->ToObject(context).ToLocal(&obj)) { + return scope.Escape(v8::Local()); + } + return scope.Escape(obj->Clone()); +#else + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(array->CloneElementAt(isolate->GetCurrentContext(), index) + .FromMaybe(v8::Local())); +#endif +} + +inline MaybeLocal Call( + v8::Local fun + , v8::Local recv + , int argc + , v8::Local argv[]) { + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + return scope.Escape(fun->Call(isolate->GetCurrentContext(), recv, argc, argv) + .FromMaybe(v8::Local())); +} + +#endif // NAN_MAYBE_43_INL_H_ diff --git a/express-server/node_modules/nan/nan_maybe_pre_43_inl.h b/express-server/node_modules/nan/nan_maybe_pre_43_inl.h new file mode 100644 index 00000000..3847296d --- /dev/null +++ b/express-server/node_modules/nan/nan_maybe_pre_43_inl.h @@ -0,0 +1,316 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_MAYBE_PRE_43_INL_H_ +#define NAN_MAYBE_PRE_43_INL_H_ + +template +class MaybeLocal { + public: + inline MaybeLocal() : val_(v8::Local()) {} + + template +# if NODE_MODULE_VERSION >= NODE_0_12_MODULE_VERSION + inline + MaybeLocal(v8::Local that) : val_(that) {} // NOLINT(runtime/explicit) +# else + inline + MaybeLocal(v8::Local that) : // NOLINT(runtime/explicit) + val_(*reinterpret_cast*>(&that)) {} +# endif + + inline bool IsEmpty() const { return val_.IsEmpty(); } + + template + inline bool ToLocal(v8::Local *out) const { + *out = val_; + return !IsEmpty(); + } + + inline v8::Local ToLocalChecked() const { +#if defined(V8_ENABLE_CHECKS) + assert(!IsEmpty() && "ToLocalChecked is Empty"); +#endif // V8_ENABLE_CHECKS + return val_; + } + + template + inline v8::Local FromMaybe(v8::Local default_value) const { + return IsEmpty() ? default_value : v8::Local(val_); + } + + private: + v8::Local val_; +}; + +template +class Maybe { + public: + inline bool IsNothing() const { return !has_value_; } + inline bool IsJust() const { return has_value_; } + + inline T FromJust() const { +#if defined(V8_ENABLE_CHECKS) + assert(IsJust() && "FromJust is Nothing"); +#endif // V8_ENABLE_CHECKS + return value_; + } + + inline T FromMaybe(const T& default_value) const { + return has_value_ ? value_ : default_value; + } + + inline bool operator==(const Maybe &other) const { + return (IsJust() == other.IsJust()) && + (!IsJust() || FromJust() == other.FromJust()); + } + + inline bool operator!=(const Maybe &other) const { + return !operator==(other); + } + + private: + Maybe() : has_value_(false) {} + explicit Maybe(const T& t) : has_value_(true), value_(t) {} + bool has_value_; + T value_; + + template + friend Maybe Nothing(); + template + friend Maybe Just(const U& u); +}; + +template +inline Maybe Nothing() { + return Maybe(); +} + +template +inline Maybe Just(const T& t) { + return Maybe(t); +} + +inline +MaybeLocal ToDetailString(v8::Handle val) { + return MaybeLocal(val->ToDetailString()); +} + +inline +MaybeLocal ToArrayIndex(v8::Handle val) { + return MaybeLocal(val->ToArrayIndex()); +} + +inline +Maybe Equals(v8::Handle a, v8::Handle(b)) { + return Just(a->Equals(b)); +} + +inline +MaybeLocal NewInstance(v8::Handle h) { + return MaybeLocal(h->NewInstance()); +} + +inline +MaybeLocal NewInstance( + v8::Local h + , int argc + , v8::Local argv[]) { + return MaybeLocal(h->NewInstance(argc, argv)); +} + +inline +MaybeLocal NewInstance(v8::Handle h) { + return MaybeLocal(h->NewInstance()); +} + +inline +MaybeLocal GetFunction(v8::Handle t) { + return MaybeLocal(t->GetFunction()); +} + +inline Maybe Set( + v8::Handle obj + , v8::Handle key + , v8::Handle value) { + return Just(obj->Set(key, value)); +} + +inline Maybe Set( + v8::Handle obj + , uint32_t index + , v8::Handle value) { + return Just(obj->Set(index, value)); +} + +#include "nan_define_own_property_helper.h" // NOLINT(build/include) + +inline Maybe DefineOwnProperty( + v8::Handle obj + , v8::Handle key + , v8::Handle value + , v8::PropertyAttribute attribs = v8::None) { + v8::PropertyAttribute current = obj->GetPropertyAttributes(key); + return imp::DefineOwnPropertyHelper(current, obj, key, value, attribs); +} + +NAN_DEPRECATED inline Maybe ForceSet( + v8::Handle obj + , v8::Handle key + , v8::Handle value + , v8::PropertyAttribute attribs = v8::None) { + return Just(obj->ForceSet(key, value, attribs)); +} + +inline MaybeLocal Get( + v8::Handle obj + , v8::Handle key) { + return MaybeLocal(obj->Get(key)); +} + +inline MaybeLocal Get( + v8::Handle obj + , uint32_t index) { + return MaybeLocal(obj->Get(index)); +} + +inline Maybe GetPropertyAttributes( + v8::Handle obj + , v8::Handle key) { + return Just(obj->GetPropertyAttributes(key)); +} + +inline Maybe Has( + v8::Handle obj + , v8::Handle key) { + return Just(obj->Has(key)); +} + +inline Maybe Has( + v8::Handle obj + , uint32_t index) { + return Just(obj->Has(index)); +} + +inline Maybe Delete( + v8::Handle obj + , v8::Handle key) { + return Just(obj->Delete(key)); +} + +inline Maybe Delete( + v8::Handle obj + , uint32_t index) { + return Just(obj->Delete(index)); +} + +inline +MaybeLocal GetPropertyNames(v8::Handle obj) { + return MaybeLocal(obj->GetPropertyNames()); +} + +inline +MaybeLocal GetOwnPropertyNames(v8::Handle obj) { + return MaybeLocal(obj->GetOwnPropertyNames()); +} + +inline Maybe SetPrototype( + v8::Handle obj + , v8::Handle prototype) { + return Just(obj->SetPrototype(prototype)); +} + +inline MaybeLocal ObjectProtoToString( + v8::Handle obj) { + return MaybeLocal(obj->ObjectProtoToString()); +} + +inline Maybe HasOwnProperty( + v8::Handle obj + , v8::Handle key) { + return Just(obj->HasOwnProperty(key)); +} + +inline Maybe HasRealNamedProperty( + v8::Handle obj + , v8::Handle key) { + return Just(obj->HasRealNamedProperty(key)); +} + +inline Maybe HasRealIndexedProperty( + v8::Handle obj + , uint32_t index) { + return Just(obj->HasRealIndexedProperty(index)); +} + +inline Maybe HasRealNamedCallbackProperty( + v8::Handle obj + , v8::Handle key) { + return Just(obj->HasRealNamedCallbackProperty(key)); +} + +inline MaybeLocal GetRealNamedPropertyInPrototypeChain( + v8::Handle obj + , v8::Handle key) { + return MaybeLocal( + obj->GetRealNamedPropertyInPrototypeChain(key)); +} + +inline MaybeLocal GetRealNamedProperty( + v8::Handle obj + , v8::Handle key) { + return MaybeLocal(obj->GetRealNamedProperty(key)); +} + +inline MaybeLocal CallAsFunction( + v8::Handle obj + , v8::Handle recv + , int argc + , v8::Handle argv[]) { + return MaybeLocal(obj->CallAsFunction(recv, argc, argv)); +} + +inline MaybeLocal CallAsConstructor( + v8::Handle obj + , int argc + , v8::Local argv[]) { + return MaybeLocal(obj->CallAsConstructor(argc, argv)); +} + +inline +MaybeLocal GetSourceLine(v8::Handle msg) { + return MaybeLocal(msg->GetSourceLine()); +} + +inline Maybe GetLineNumber(v8::Handle msg) { + return Just(msg->GetLineNumber()); +} + +inline Maybe GetStartColumn(v8::Handle msg) { + return Just(msg->GetStartColumn()); +} + +inline Maybe GetEndColumn(v8::Handle msg) { + return Just(msg->GetEndColumn()); +} + +inline MaybeLocal CloneElementAt( + v8::Handle array + , uint32_t index) { + return MaybeLocal(array->CloneElementAt(index)); +} + +inline MaybeLocal Call( + v8::Local fun + , v8::Local recv + , int argc + , v8::Local argv[]) { + return MaybeLocal(fun->Call(recv, argc, argv)); +} + +#endif // NAN_MAYBE_PRE_43_INL_H_ diff --git a/express-server/node_modules/nan/nan_new.h b/express-server/node_modules/nan/nan_new.h new file mode 100644 index 00000000..cdf8bbe4 --- /dev/null +++ b/express-server/node_modules/nan/nan_new.h @@ -0,0 +1,340 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_NEW_H_ +#define NAN_NEW_H_ + +namespace imp { // scnr + +// TODO(agnat): Generalize +template v8::Local To(v8::Local i); + +template <> +inline +v8::Local +To(v8::Local i) { + return Nan::To(i).ToLocalChecked(); +} + +template <> +inline +v8::Local +To(v8::Local i) { + return Nan::To(i).ToLocalChecked(); +} + +template <> +inline +v8::Local +To(v8::Local i) { + return Nan::To(i).ToLocalChecked(); +} + +template struct FactoryBase { + typedef v8::Local return_t; +}; + +template struct MaybeFactoryBase { + typedef MaybeLocal return_t; +}; + +template struct Factory; + +template <> +struct Factory : FactoryBase { + static inline return_t New(); + static inline return_t New(int length); +}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(bool value); +}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(bool value); +}; + +template <> +struct Factory : FactoryBase { + static inline + return_t + New( v8::ExtensionConfiguration* extensions = NULL + , v8::Local tmpl = v8::Local() + , v8::Local obj = v8::Local()); +}; + +template <> +struct Factory : MaybeFactoryBase { + static inline return_t New(double value); +}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(void *value); +}; + +template <> +struct Factory : FactoryBase { + static inline + return_t + New( FunctionCallback callback + , v8::Local data = v8::Local()); +}; + +template <> +struct Factory : FactoryBase { + static inline + return_t + New( FunctionCallback callback = NULL + , v8::Local data = v8::Local() + , v8::Local signature = v8::Local()); +}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(double value); +}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(double value); +}; + +template +struct IntegerFactory : FactoryBase { + typedef typename FactoryBase::return_t return_t; + static inline return_t New(int32_t value); + static inline return_t New(uint32_t value); +}; + +template <> +struct Factory : IntegerFactory {}; + +template <> +struct Factory : IntegerFactory {}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(int32_t value); + static inline return_t New(uint32_t value); +}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(); +}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(); +}; + +template <> +struct Factory : MaybeFactoryBase { + static inline return_t New( + v8::Local pattern, v8::RegExp::Flags flags); +}; + +template <> +struct Factory : MaybeFactoryBase { + static inline return_t New( v8::Local source); + static inline return_t New( v8::Local source + , v8::ScriptOrigin const& origin); +}; + +template <> +struct Factory : FactoryBase { + typedef v8::Local FTH; + static inline return_t New(FTH receiver = FTH()); +}; + +template <> +struct Factory : MaybeFactoryBase { + static inline return_t New(); + static inline return_t New(const char *value, int length = -1); + static inline return_t New(const uint16_t *value, int length = -1); + static inline return_t New(std::string const& value); + + static inline return_t New(v8::String::ExternalStringResource * value); + static inline return_t New(ExternalOneByteStringResource * value); +}; + +template <> +struct Factory : FactoryBase { + static inline return_t New(v8::Local value); +}; + +} // end of namespace imp + +#if (NODE_MODULE_VERSION >= 12) + +namespace imp { + +template <> +struct Factory : MaybeFactoryBase { + static inline return_t New( v8::Local source); + static inline return_t New( v8::Local source + , v8::ScriptOrigin const& origin); +}; + +} // end of namespace imp + +# include "nan_implementation_12_inl.h" + +#else // NODE_MODULE_VERSION >= 12 + +# include "nan_implementation_pre_12_inl.h" + +#endif + +//=== API ====================================================================== + +template +typename imp::Factory::return_t +New() { + return imp::Factory::New(); +} + +template +typename imp::Factory::return_t +New(A0 arg0) { + return imp::Factory::New(arg0); +} + +template +typename imp::Factory::return_t +New(A0 arg0, A1 arg1) { + return imp::Factory::New(arg0, arg1); +} + +template +typename imp::Factory::return_t +New(A0 arg0, A1 arg1, A2 arg2) { + return imp::Factory::New(arg0, arg1, arg2); +} + +template +typename imp::Factory::return_t +New(A0 arg0, A1 arg1, A2 arg2, A3 arg3) { + return imp::Factory::New(arg0, arg1, arg2, arg3); +} + +// Note(agnat): When passing overloaded function pointers to template functions +// as generic arguments the compiler needs help in picking the right overload. +// These two functions handle New and New with +// all argument variations. + +// v8::Function and v8::FunctionTemplate with one or two arguments +template +typename imp::Factory::return_t +New( FunctionCallback callback + , v8::Local data = v8::Local()) { + return imp::Factory::New(callback, data); +} + +// v8::Function and v8::FunctionTemplate with three arguments +template +typename imp::Factory::return_t +New( FunctionCallback callback + , v8::Local data = v8::Local() + , A2 a2 = A2()) { + return imp::Factory::New(callback, data, a2); +} + +// Convenience + +#if NODE_MODULE_VERSION < IOJS_3_0_MODULE_VERSION +template inline v8::Local New(v8::Handle h); +#endif + +#if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION +template + inline v8::Local New(v8::Persistent const& p); +#else +template inline v8::Local New(v8::Persistent const& p); +#endif +template +inline v8::Local New(Persistent const& p); +template +inline v8::Local New(Global const& p); + +inline +imp::Factory::return_t +New(bool value) { + return New(value); +} + +inline +imp::Factory::return_t +New(int32_t value) { + return New(value); +} + +inline +imp::Factory::return_t +New(uint32_t value) { + return New(value); +} + +inline +imp::Factory::return_t +New(double value) { + return New(value); +} + +inline +imp::Factory::return_t +New(std::string const& value) { // NOLINT(build/include_what_you_use) + return New(value); +} + +inline +imp::Factory::return_t +New(const char * value, int length) { + return New(value, length); +} + +inline +imp::Factory::return_t +New(const uint16_t * value, int length) { + return New(value, length); +} + +inline +imp::Factory::return_t +New(const char * value) { + return New(value); +} + +inline +imp::Factory::return_t +New(const uint16_t * value) { + return New(value); +} + +inline +imp::Factory::return_t +New(v8::String::ExternalStringResource * value) { + return New(value); +} + +inline +imp::Factory::return_t +New(ExternalOneByteStringResource * value) { + return New(value); +} + +inline +imp::Factory::return_t +New(v8::Local pattern, v8::RegExp::Flags flags) { + return New(pattern, flags); +} + +#endif // NAN_NEW_H_ diff --git a/express-server/node_modules/nan/nan_object_wrap.h b/express-server/node_modules/nan/nan_object_wrap.h new file mode 100644 index 00000000..45f43dd3 --- /dev/null +++ b/express-server/node_modules/nan/nan_object_wrap.h @@ -0,0 +1,158 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_OBJECT_WRAP_H_ +#define NAN_OBJECT_WRAP_H_ + +class ObjectWrap { + public: + ObjectWrap() { + refs_ = 0; + } + + + virtual ~ObjectWrap() { + if (persistent().IsEmpty()) { + return; + } + + assert(persistent().IsNearDeath()); + persistent().ClearWeak(); + persistent().Reset(); + } + + + template + static inline T* Unwrap(v8::Local object) { + assert(!object.IsEmpty()); + assert(object->InternalFieldCount() > 0); + // Cast to ObjectWrap before casting to T. A direct cast from void + // to T won't work right when T has more than one base class. + void* ptr = GetInternalFieldPointer(object, 0); + ObjectWrap* wrap = static_cast(ptr); + return static_cast(wrap); + } + + + inline v8::Local handle() const { + return New(handle_); + } + + + inline Persistent& persistent() { + return handle_; + } + + + protected: + inline void Wrap(v8::Local object) { + assert(persistent().IsEmpty()); + assert(object->InternalFieldCount() > 0); + SetInternalFieldPointer(object, 0, this); + persistent().Reset(object); + MakeWeak(); + } + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + + inline void MakeWeak() { + persistent().v8::PersistentBase::SetWeak( + this, WeakCallback, v8::WeakCallbackType::kParameter); +#if NODE_MAJOR_VERSION < 10 + // FIXME(bnoordhuis) Probably superfluous in older Node.js versions too. + persistent().MarkIndependent(); +#endif + } + +#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + + inline void MakeWeak() { + persistent().v8::PersistentBase::SetWeak(this, WeakCallback); + persistent().MarkIndependent(); + } + +#else + + inline void MakeWeak() { + persistent().persistent.MakeWeak(this, WeakCallback); + persistent().MarkIndependent(); + } + +#endif + + /* Ref() marks the object as being attached to an event loop. + * Refed objects will not be garbage collected, even if + * all references are lost. + */ + virtual void Ref() { + assert(!persistent().IsEmpty()); + persistent().ClearWeak(); + refs_++; + } + + /* Unref() marks an object as detached from the event loop. This is its + * default state. When an object with a "weak" reference changes from + * attached to detached state it will be freed. Be careful not to access + * the object after making this call as it might be gone! + * (A "weak reference" means an object that only has a + * persistant handle.) + * + * DO NOT CALL THIS FROM DESTRUCTOR + */ + virtual void Unref() { + assert(!persistent().IsEmpty()); + assert(!persistent().IsWeak()); + assert(refs_ > 0); + if (--refs_ == 0) + MakeWeak(); + } + + int refs_; // ro + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(ObjectWrap) +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + + static void + WeakCallback(v8::WeakCallbackInfo const& info) { + ObjectWrap* wrap = info.GetParameter(); + assert(wrap->refs_ == 0); + assert(wrap->handle_.IsNearDeath()); + wrap->handle_.Reset(); + delete wrap; + } + +#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + + static void + WeakCallback(v8::WeakCallbackData const& data) { + ObjectWrap* wrap = data.GetParameter(); + assert(wrap->refs_ == 0); + assert(wrap->handle_.IsNearDeath()); + wrap->handle_.Reset(); + delete wrap; + } + +#else + + static void WeakCallback(v8::Persistent value, void *data) { + ObjectWrap *wrap = static_cast(data); + assert(wrap->refs_ == 0); + assert(wrap->handle_.IsNearDeath()); + wrap->handle_.Reset(); + delete wrap; + } + +#endif + Persistent handle_; +}; + + +#endif // NAN_OBJECT_WRAP_H_ diff --git a/express-server/node_modules/nan/nan_persistent_12_inl.h b/express-server/node_modules/nan/nan_persistent_12_inl.h new file mode 100644 index 00000000..d9649e86 --- /dev/null +++ b/express-server/node_modules/nan/nan_persistent_12_inl.h @@ -0,0 +1,132 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_PERSISTENT_12_INL_H_ +#define NAN_PERSISTENT_12_INL_H_ + +template class Persistent : + public v8::Persistent { + public: + inline Persistent() : v8::Persistent() {} + + template inline Persistent(v8::Local that) : + v8::Persistent(v8::Isolate::GetCurrent(), that) {} + + template + inline + Persistent(const v8::Persistent &that) : // NOLINT(runtime/explicit) + v8::Persistent(v8::Isolate::GetCurrent(), that) {} + + inline void Reset() { v8::PersistentBase::Reset(); } + + template + inline void Reset(const v8::Local &other) { + v8::PersistentBase::Reset(v8::Isolate::GetCurrent(), other); + } + + template + inline void Reset(const v8::PersistentBase &other) { + v8::PersistentBase::Reset(v8::Isolate::GetCurrent(), other); + } + + template + inline void SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type); + + private: + inline T *operator*() const { return *PersistentBase::persistent; } + + template + inline void Copy(const Persistent &that) { + TYPE_CHECK(T, S); + + this->Reset(); + + if (!that.IsEmpty()) { + this->Reset(that); + M::Copy(that, this); + } + } +}; + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +template +class Global : public v8::Global { + public: + inline Global() : v8::Global() {} + + template inline Global(v8::Local that) : + v8::Global(v8::Isolate::GetCurrent(), that) {} + + template + inline + Global(const v8::PersistentBase &that) : // NOLINT(runtime/explicit) + v8::Global(v8::Isolate::GetCurrent(), that) {} + + inline void Reset() { v8::PersistentBase::Reset(); } + + template + inline void Reset(const v8::Local &other) { + v8::PersistentBase::Reset(v8::Isolate::GetCurrent(), other); + } + + template + inline void Reset(const v8::PersistentBase &other) { + v8::PersistentBase::Reset(v8::Isolate::GetCurrent(), other); + } + + template + inline void SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type) { + reinterpret_cast*>(this)->SetWeak( + parameter, callback, type); + } +}; +#else +template +class Global : public v8::UniquePersistent { + public: + inline Global() : v8::UniquePersistent() {} + + template inline Global(v8::Local that) : + v8::UniquePersistent(v8::Isolate::GetCurrent(), that) {} + + template + inline + Global(const v8::PersistentBase &that) : // NOLINT(runtime/explicit) + v8::UniquePersistent(v8::Isolate::GetCurrent(), that) {} + + inline void Reset() { v8::PersistentBase::Reset(); } + + template + inline void Reset(const v8::Local &other) { + v8::PersistentBase::Reset(v8::Isolate::GetCurrent(), other); + } + + template + inline void Reset(const v8::PersistentBase &other) { + v8::PersistentBase::Reset(v8::Isolate::GetCurrent(), other); + } + + template + inline void SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type) { + reinterpret_cast*>(this)->SetWeak( + parameter, callback, type); + } +}; +#endif + +#endif // NAN_PERSISTENT_12_INL_H_ diff --git a/express-server/node_modules/nan/nan_persistent_pre_12_inl.h b/express-server/node_modules/nan/nan_persistent_pre_12_inl.h new file mode 100644 index 00000000..4c9c59da --- /dev/null +++ b/express-server/node_modules/nan/nan_persistent_pre_12_inl.h @@ -0,0 +1,242 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_PERSISTENT_PRE_12_INL_H_ +#define NAN_PERSISTENT_PRE_12_INL_H_ + +template +class PersistentBase { + v8::Persistent persistent; + template + friend v8::Local New(const PersistentBase &p); + template + friend v8::Local New(const Persistent &p); + template + friend v8::Local New(const Global &p); + template friend class ReturnValue; + + public: + inline PersistentBase() : + persistent() {} + + inline void Reset() { + persistent.Dispose(); + persistent.Clear(); + } + + template + inline void Reset(const v8::Local &other) { + TYPE_CHECK(T, S); + + if (!persistent.IsEmpty()) { + persistent.Dispose(); + } + + if (other.IsEmpty()) { + persistent.Clear(); + } else { + persistent = v8::Persistent::New(other); + } + } + + template + inline void Reset(const PersistentBase &other) { + TYPE_CHECK(T, S); + + if (!persistent.IsEmpty()) { + persistent.Dispose(); + } + + if (other.IsEmpty()) { + persistent.Clear(); + } else { + persistent = v8::Persistent::New(other.persistent); + } + } + + inline bool IsEmpty() const { return persistent.IsEmpty(); } + + inline void Empty() { persistent.Clear(); } + + template + inline bool operator==(const PersistentBase &that) const { + return this->persistent == that.persistent; + } + + template + inline bool operator==(const v8::Local &that) const { + return this->persistent == that; + } + + template + inline bool operator!=(const PersistentBase &that) const { + return !operator==(that); + } + + template + inline bool operator!=(const v8::Local &that) const { + return !operator==(that); + } + + template + inline void SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type); + + inline void ClearWeak() { persistent.ClearWeak(); } + + inline void MarkIndependent() { persistent.MarkIndependent(); } + + inline bool IsIndependent() const { return persistent.IsIndependent(); } + + inline bool IsNearDeath() const { return persistent.IsNearDeath(); } + + inline bool IsWeak() const { return persistent.IsWeak(); } + + private: + inline explicit PersistentBase(v8::Persistent that) : + persistent(that) { } + inline explicit PersistentBase(T *val) : persistent(val) {} + template friend class Persistent; + template friend class Global; + friend class ObjectWrap; +}; + +template +class NonCopyablePersistentTraits { + public: + typedef Persistent > + NonCopyablePersistent; + static const bool kResetInDestructor = false; + template + inline static void Copy(const Persistent &source, + NonCopyablePersistent *dest) { + Uncompilable(); + } + + template inline static void Uncompilable() { + TYPE_CHECK(O, v8::Primitive); + } +}; + +template +struct CopyablePersistentTraits { + typedef Persistent > CopyablePersistent; + static const bool kResetInDestructor = true; + template + static inline void Copy(const Persistent &source, + CopyablePersistent *dest) {} +}; + +template class Persistent : + public PersistentBase { + public: + inline Persistent() {} + + template inline Persistent(v8::Handle that) + : PersistentBase(v8::Persistent::New(that)) { + TYPE_CHECK(T, S); + } + + inline Persistent(const Persistent &that) : PersistentBase() { + Copy(that); + } + + template + inline Persistent(const Persistent &that) : + PersistentBase() { + Copy(that); + } + + inline Persistent &operator=(const Persistent &that) { + Copy(that); + return *this; + } + + template + inline Persistent &operator=(const Persistent &that) { + Copy(that); + return *this; + } + + inline ~Persistent() { + if (M::kResetInDestructor) this->Reset(); + } + + private: + inline T *operator*() const { return *PersistentBase::persistent; } + + template + inline void Copy(const Persistent &that) { + TYPE_CHECK(T, S); + + this->Reset(); + + if (!that.IsEmpty()) { + this->persistent = v8::Persistent::New(that.persistent); + M::Copy(that, this); + } + } +}; + +template +class Global : public PersistentBase { + struct RValue { + inline explicit RValue(Global* obj) : object(obj) {} + Global* object; + }; + + public: + inline Global() : PersistentBase(0) { } + + template + inline Global(v8::Local that) // NOLINT(runtime/explicit) + : PersistentBase(v8::Persistent::New(that)) { + TYPE_CHECK(T, S); + } + + template + inline Global(const PersistentBase &that) // NOLINT(runtime/explicit) + : PersistentBase(that) { + TYPE_CHECK(T, S); + } + /** + * Move constructor. + */ + inline Global(RValue rvalue) // NOLINT(runtime/explicit) + : PersistentBase(rvalue.object->persistent) { + rvalue.object->Reset(); + } + inline ~Global() { this->Reset(); } + /** + * Move via assignment. + */ + template + inline Global &operator=(Global rhs) { + TYPE_CHECK(T, S); + this->Reset(rhs.persistent); + rhs.Reset(); + return *this; + } + /** + * Cast operator for moves. + */ + inline operator RValue() { return RValue(this); } + /** + * Pass allows returning uniques from functions, etc. + */ + Global Pass() { return Global(RValue(this)); } + + private: + Global(Global &); + void operator=(Global &); + template friend class ReturnValue; +}; + +#endif // NAN_PERSISTENT_PRE_12_INL_H_ diff --git a/express-server/node_modules/nan/nan_private.h b/express-server/node_modules/nan/nan_private.h new file mode 100644 index 00000000..15f44cc8 --- /dev/null +++ b/express-server/node_modules/nan/nan_private.h @@ -0,0 +1,73 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_PRIVATE_H_ +#define NAN_PRIVATE_H_ + +inline Maybe +HasPrivate(v8::Local object, v8::Local key) { + HandleScope scope; +#if NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::Local context = isolate->GetCurrentContext(); + v8::Local private_key = v8::Private::ForApi(isolate, key); + return object->HasPrivate(context, private_key); +#else + return Just(!object->GetHiddenValue(key).IsEmpty()); +#endif +} + +inline MaybeLocal +GetPrivate(v8::Local object, v8::Local key) { +#if NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::EscapableHandleScope scope(isolate); + v8::Local context = isolate->GetCurrentContext(); + v8::Local private_key = v8::Private::ForApi(isolate, key); + v8::MaybeLocal v = object->GetPrivate(context, private_key); + return scope.Escape(v.ToLocalChecked()); +#else + EscapableHandleScope scope; + v8::Local v = object->GetHiddenValue(key); + if (v.IsEmpty()) { + v = Undefined(); + } + return scope.Escape(v); +#endif +} + +inline Maybe SetPrivate( + v8::Local object, + v8::Local key, + v8::Local value) { +#if NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION + HandleScope scope; + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::Local context = isolate->GetCurrentContext(); + v8::Local private_key = v8::Private::ForApi(isolate, key); + return object->SetPrivate(context, private_key, value); +#else + return Just(object->SetHiddenValue(key, value)); +#endif +} + +inline Maybe DeletePrivate( + v8::Local object, + v8::Local key) { +#if NODE_MODULE_VERSION >= NODE_6_0_MODULE_VERSION + HandleScope scope; + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::Local private_key = v8::Private::ForApi(isolate, key); + return object->DeletePrivate(isolate->GetCurrentContext(), private_key); +#else + return Just(object->DeleteHiddenValue(key)); +#endif +} + +#endif // NAN_PRIVATE_H_ + diff --git a/express-server/node_modules/nan/nan_string_bytes.h b/express-server/node_modules/nan/nan_string_bytes.h new file mode 100644 index 00000000..a2e6437d --- /dev/null +++ b/express-server/node_modules/nan/nan_string_bytes.h @@ -0,0 +1,305 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// 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. + +#ifndef NAN_STRING_BYTES_H_ +#define NAN_STRING_BYTES_H_ + +// Decodes a v8::Local or Buffer to a raw char* + +namespace imp { + +using v8::Local; +using v8::Object; +using v8::String; +using v8::Value; + + +//// Base 64 //// + +#define base64_encoded_size(size) ((size + 2 - ((size + 2) % 3)) / 3 * 4) + + + +//// HEX //// + +static bool contains_non_ascii_slow(const char* buf, size_t len) { + for (size_t i = 0; i < len; ++i) { + if (buf[i] & 0x80) return true; + } + return false; +} + + +static bool contains_non_ascii(const char* src, size_t len) { + if (len < 16) { + return contains_non_ascii_slow(src, len); + } + + const unsigned bytes_per_word = sizeof(void*); + const unsigned align_mask = bytes_per_word - 1; + const unsigned unaligned = reinterpret_cast(src) & align_mask; + + if (unaligned > 0) { + const unsigned n = bytes_per_word - unaligned; + if (contains_non_ascii_slow(src, n)) return true; + src += n; + len -= n; + } + + +#if defined(__x86_64__) || defined(_WIN64) + const uintptr_t mask = 0x8080808080808080ll; +#else + const uintptr_t mask = 0x80808080l; +#endif + + const uintptr_t* srcw = reinterpret_cast(src); + + for (size_t i = 0, n = len / bytes_per_word; i < n; ++i) { + if (srcw[i] & mask) return true; + } + + const unsigned remainder = len & align_mask; + if (remainder > 0) { + const size_t offset = len - remainder; + if (contains_non_ascii_slow(src + offset, remainder)) return true; + } + + return false; +} + + +static void force_ascii_slow(const char* src, char* dst, size_t len) { + for (size_t i = 0; i < len; ++i) { + dst[i] = src[i] & 0x7f; + } +} + + +static void force_ascii(const char* src, char* dst, size_t len) { + if (len < 16) { + force_ascii_slow(src, dst, len); + return; + } + + const unsigned bytes_per_word = sizeof(void*); + const unsigned align_mask = bytes_per_word - 1; + const unsigned src_unalign = reinterpret_cast(src) & align_mask; + const unsigned dst_unalign = reinterpret_cast(dst) & align_mask; + + if (src_unalign > 0) { + if (src_unalign == dst_unalign) { + const unsigned unalign = bytes_per_word - src_unalign; + force_ascii_slow(src, dst, unalign); + src += unalign; + dst += unalign; + len -= src_unalign; + } else { + force_ascii_slow(src, dst, len); + return; + } + } + +#if defined(__x86_64__) || defined(_WIN64) + const uintptr_t mask = ~0x8080808080808080ll; +#else + const uintptr_t mask = ~0x80808080l; +#endif + + const uintptr_t* srcw = reinterpret_cast(src); + uintptr_t* dstw = reinterpret_cast(dst); + + for (size_t i = 0, n = len / bytes_per_word; i < n; ++i) { + dstw[i] = srcw[i] & mask; + } + + const unsigned remainder = len & align_mask; + if (remainder > 0) { + const size_t offset = len - remainder; + force_ascii_slow(src + offset, dst + offset, remainder); + } +} + + +static size_t base64_encode(const char* src, + size_t slen, + char* dst, + size_t dlen) { + // We know how much we'll write, just make sure that there's space. + assert(dlen >= base64_encoded_size(slen) && + "not enough space provided for base64 encode"); + + dlen = base64_encoded_size(slen); + + unsigned a; + unsigned b; + unsigned c; + unsigned i; + unsigned k; + unsigned n; + + static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + + i = 0; + k = 0; + n = slen / 3 * 3; + + while (i < n) { + a = src[i + 0] & 0xff; + b = src[i + 1] & 0xff; + c = src[i + 2] & 0xff; + + dst[k + 0] = table[a >> 2]; + dst[k + 1] = table[((a & 3) << 4) | (b >> 4)]; + dst[k + 2] = table[((b & 0x0f) << 2) | (c >> 6)]; + dst[k + 3] = table[c & 0x3f]; + + i += 3; + k += 4; + } + + if (n != slen) { + switch (slen - n) { + case 1: + a = src[i + 0] & 0xff; + dst[k + 0] = table[a >> 2]; + dst[k + 1] = table[(a & 3) << 4]; + dst[k + 2] = '='; + dst[k + 3] = '='; + break; + + case 2: + a = src[i + 0] & 0xff; + b = src[i + 1] & 0xff; + dst[k + 0] = table[a >> 2]; + dst[k + 1] = table[((a & 3) << 4) | (b >> 4)]; + dst[k + 2] = table[(b & 0x0f) << 2]; + dst[k + 3] = '='; + break; + } + } + + return dlen; +} + + +static size_t hex_encode(const char* src, size_t slen, char* dst, size_t dlen) { + // We know how much we'll write, just make sure that there's space. + assert(dlen >= slen * 2 && + "not enough space provided for hex encode"); + + dlen = slen * 2; + for (uint32_t i = 0, k = 0; k < dlen; i += 1, k += 2) { + static const char hex[] = "0123456789abcdef"; + uint8_t val = static_cast(src[i]); + dst[k + 0] = hex[val >> 4]; + dst[k + 1] = hex[val & 15]; + } + + return dlen; +} + + + +static Local Encode(const char* buf, + size_t buflen, + enum Encoding encoding) { + assert(buflen <= node::Buffer::kMaxLength); + if (!buflen && encoding != BUFFER) + return New("").ToLocalChecked(); + + Local val; + switch (encoding) { + case BUFFER: + return CopyBuffer(buf, buflen).ToLocalChecked(); + + case ASCII: + if (contains_non_ascii(buf, buflen)) { + char* out = new char[buflen]; + force_ascii(buf, out, buflen); + val = New(out, buflen).ToLocalChecked(); + delete[] out; + } else { + val = New(buf, buflen).ToLocalChecked(); + } + break; + + case UTF8: + val = New(buf, buflen).ToLocalChecked(); + break; + + case BINARY: { + // TODO(isaacs) use ExternalTwoByteString? + const unsigned char *cbuf = reinterpret_cast(buf); + uint16_t * twobytebuf = new uint16_t[buflen]; + for (size_t i = 0; i < buflen; i++) { + // XXX is the following line platform independent? + twobytebuf[i] = cbuf[i]; + } + val = New(twobytebuf, buflen).ToLocalChecked(); + delete[] twobytebuf; + break; + } + + case BASE64: { + size_t dlen = base64_encoded_size(buflen); + char* dst = new char[dlen]; + + size_t written = base64_encode(buf, buflen, dst, dlen); + assert(written == dlen); + + val = New(dst, dlen).ToLocalChecked(); + delete[] dst; + break; + } + + case UCS2: { + const uint16_t* data = reinterpret_cast(buf); + val = New(data, buflen / 2).ToLocalChecked(); + break; + } + + case HEX: { + size_t dlen = buflen * 2; + char* dst = new char[dlen]; + size_t written = hex_encode(buf, buflen, dst, dlen); + assert(written == dlen); + + val = New(dst, dlen).ToLocalChecked(); + delete[] dst; + break; + } + + default: + assert(0 && "unknown encoding"); + break; + } + + return val; +} + +#undef base64_encoded_size + +} // end of namespace imp + +#endif // NAN_STRING_BYTES_H_ diff --git a/express-server/node_modules/nan/nan_typedarray_contents.h b/express-server/node_modules/nan/nan_typedarray_contents.h new file mode 100644 index 00000000..d28ae323 --- /dev/null +++ b/express-server/node_modules/nan/nan_typedarray_contents.h @@ -0,0 +1,90 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_TYPEDARRAY_CONTENTS_H_ +#define NAN_TYPEDARRAY_CONTENTS_H_ + +template +class TypedArrayContents { + public: + inline explicit TypedArrayContents(v8::Local from) : + length_(0), data_(NULL) { + HandleScope scope; + + size_t length = 0; + void* data = NULL; + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + + if (from->IsArrayBufferView()) { + v8::Local array = + v8::Local::Cast(from); + + const size_t byte_length = array->ByteLength(); + const ptrdiff_t byte_offset = array->ByteOffset(); + v8::Local buffer = array->Buffer(); + + length = byte_length / sizeof(T); + data = static_cast(buffer->GetContents().Data()) + byte_offset; + } + +#else + + if (from->IsObject() && !from->IsNull()) { + v8::Local array = v8::Local::Cast(from); + + MaybeLocal buffer = Get(array, + New("buffer").ToLocalChecked()); + MaybeLocal byte_length = Get(array, + New("byteLength").ToLocalChecked()); + MaybeLocal byte_offset = Get(array, + New("byteOffset").ToLocalChecked()); + + if (!buffer.IsEmpty() && + !byte_length.IsEmpty() && byte_length.ToLocalChecked()->IsUint32() && + !byte_offset.IsEmpty() && byte_offset.ToLocalChecked()->IsUint32()) { + data = array->GetIndexedPropertiesExternalArrayData(); + if(data) { + length = byte_length.ToLocalChecked()->Uint32Value() / sizeof(T); + } + } + } + +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1900 || __cplusplus >= 201103L + assert(reinterpret_cast(data) % alignof (T) == 0); +#elif defined(_MSC_VER) && _MSC_VER >= 1600 || defined(__GNUC__) + assert(reinterpret_cast(data) % __alignof(T) == 0); +#else + assert(reinterpret_cast(data) % sizeof (T) == 0); +#endif + + length_ = length; + data_ = static_cast(data); + } + + inline size_t length() const { return length_; } + inline T* operator*() { return data_; } + inline const T* operator*() const { return data_; } + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(TypedArrayContents) + + //Disable heap allocation + void *operator new(size_t size); + void operator delete(void *, size_t) { + abort(); + } + + size_t length_; + T* data_; +}; + +#endif // NAN_TYPEDARRAY_CONTENTS_H_ diff --git a/express-server/node_modules/nan/nan_weak.h b/express-server/node_modules/nan/nan_weak.h new file mode 100644 index 00000000..7e7ab07b --- /dev/null +++ b/express-server/node_modules/nan/nan_weak.h @@ -0,0 +1,437 @@ +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +#ifndef NAN_WEAK_H_ +#define NAN_WEAK_H_ + +static const int kInternalFieldsInWeakCallback = 2; +static const int kNoInternalFieldIndex = -1; + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +# define NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ \ + v8::WeakCallbackInfo > const& +# define NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ \ + NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ +# define NAN_WEAK_PARAMETER_CALLBACK_SIG_ NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ +# define NAN_WEAK_TWOFIELD_CALLBACK_SIG_ NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ +#elif NODE_MODULE_VERSION > IOJS_1_1_MODULE_VERSION +# define NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ \ + v8::PhantomCallbackData > const& +# define NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ \ + NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ +# define NAN_WEAK_PARAMETER_CALLBACK_SIG_ NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ +# define NAN_WEAK_TWOFIELD_CALLBACK_SIG_ NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ +#elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION +# define NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ \ + v8::PhantomCallbackData > const& +# define NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ \ + v8::InternalFieldsCallbackData, void> const& +# define NAN_WEAK_PARAMETER_CALLBACK_SIG_ NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ +# define NAN_WEAK_TWOFIELD_CALLBACK_SIG_ NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ +#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION +# define NAN_WEAK_CALLBACK_DATA_TYPE_ \ + v8::WeakCallbackData > const& +# define NAN_WEAK_CALLBACK_SIG_ NAN_WEAK_CALLBACK_DATA_TYPE_ +#else +# define NAN_WEAK_CALLBACK_DATA_TYPE_ void * +# define NAN_WEAK_CALLBACK_SIG_ \ + v8::Persistent, NAN_WEAK_CALLBACK_DATA_TYPE_ +#endif + +template +class WeakCallbackInfo { + public: + typedef void (*Callback)(const WeakCallbackInfo& data); + WeakCallbackInfo( + Persistent *persistent + , Callback callback + , void *parameter + , void *field1 = 0 + , void *field2 = 0) : + callback_(callback), isolate_(0), parameter_(parameter) { + std::memcpy(&persistent_, persistent, sizeof (v8::Persistent)); + internal_fields_[0] = field1; + internal_fields_[1] = field2; + } + inline v8::Isolate *GetIsolate() const { return isolate_; } + inline T *GetParameter() const { return static_cast(parameter_); } + inline void *GetInternalField(int index) const { + assert((index == 0 || index == 1) && "internal field index out of bounds"); + if (index == 0) { + return internal_fields_[0]; + } else { + return internal_fields_[1]; + } + } + + private: + NAN_DISALLOW_ASSIGN_COPY_MOVE(WeakCallbackInfo) + Callback callback_; + v8::Isolate *isolate_; + void *parameter_; + void *internal_fields_[kInternalFieldsInWeakCallback]; + v8::Persistent persistent_; + template friend class Persistent; + template friend class PersistentBase; +#if NODE_MODULE_VERSION <= NODE_0_12_MODULE_VERSION +# if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + template + static void invoke(NAN_WEAK_CALLBACK_SIG_ data); + template + static WeakCallbackInfo *unwrap(NAN_WEAK_CALLBACK_DATA_TYPE_ data); +# else + static void invoke(NAN_WEAK_CALLBACK_SIG_ data); + static WeakCallbackInfo *unwrap(NAN_WEAK_CALLBACK_DATA_TYPE_ data); +# endif +#else +# if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + template + static void invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data); + template + static void invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data); +# else + static void invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data); + static void invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data); +# endif + static WeakCallbackInfo *unwrapparameter( + NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data); + static WeakCallbackInfo *unwraptwofield( + NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data); +#endif +}; + + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) + +template +template +void +WeakCallbackInfo::invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data) { + WeakCallbackInfo *cbinfo = unwrapparameter(data); + if (isFirstPass) { + cbinfo->persistent_.Reset(); + data.SetSecondPassCallback(invokeparameter); + } else { + cbinfo->callback_(*cbinfo); + delete cbinfo; + } +} + +template +template +void +WeakCallbackInfo::invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data) { + WeakCallbackInfo *cbinfo = unwraptwofield(data); + if (isFirstPass) { + cbinfo->persistent_.Reset(); + data.SetSecondPassCallback(invoketwofield); + } else { + cbinfo->callback_(*cbinfo); + delete cbinfo; + } +} + +template +WeakCallbackInfo *WeakCallbackInfo::unwrapparameter( + NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data) { + WeakCallbackInfo *cbinfo = + static_cast*>(data.GetParameter()); + cbinfo->isolate_ = data.GetIsolate(); + return cbinfo; +} + +template +WeakCallbackInfo *WeakCallbackInfo::unwraptwofield( + NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data) { + WeakCallbackInfo *cbinfo = + static_cast*>(data.GetInternalField(0)); + cbinfo->isolate_ = data.GetIsolate(); + return cbinfo; +} + +#undef NAN_WEAK_PARAMETER_CALLBACK_SIG_ +#undef NAN_WEAK_TWOFIELD_CALLBACK_SIG_ +#undef NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ +#undef NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ +# elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION + +template +void +WeakCallbackInfo::invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data) { + WeakCallbackInfo *cbinfo = unwrapparameter(data); + cbinfo->persistent_.Reset(); + cbinfo->callback_(*cbinfo); + delete cbinfo; +} + +template +void +WeakCallbackInfo::invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data) { + WeakCallbackInfo *cbinfo = unwraptwofield(data); + cbinfo->persistent_.Reset(); + cbinfo->callback_(*cbinfo); + delete cbinfo; +} + +template +WeakCallbackInfo *WeakCallbackInfo::unwrapparameter( + NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data) { + WeakCallbackInfo *cbinfo = + static_cast*>(data.GetParameter()); + cbinfo->isolate_ = data.GetIsolate(); + return cbinfo; +} + +template +WeakCallbackInfo *WeakCallbackInfo::unwraptwofield( + NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data) { + WeakCallbackInfo *cbinfo = + static_cast*>(data.GetInternalField1()); + cbinfo->isolate_ = data.GetIsolate(); + return cbinfo; +} + +#undef NAN_WEAK_PARAMETER_CALLBACK_SIG_ +#undef NAN_WEAK_TWOFIELD_CALLBACK_SIG_ +#undef NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ +#undef NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ +#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION + +template +template +void WeakCallbackInfo::invoke(NAN_WEAK_CALLBACK_SIG_ data) { + WeakCallbackInfo *cbinfo = unwrap(data); + cbinfo->persistent_.Reset(); + cbinfo->callback_(*cbinfo); + delete cbinfo; +} + +template +template +WeakCallbackInfo *WeakCallbackInfo::unwrap( + NAN_WEAK_CALLBACK_DATA_TYPE_ data) { + void *parameter = data.GetParameter(); + WeakCallbackInfo *cbinfo = + static_cast*>(parameter); + cbinfo->isolate_ = data.GetIsolate(); + return cbinfo; +} + +#undef NAN_WEAK_CALLBACK_SIG_ +#undef NAN_WEAK_CALLBACK_DATA_TYPE_ +#else + +template +void WeakCallbackInfo::invoke(NAN_WEAK_CALLBACK_SIG_ data) { + WeakCallbackInfo *cbinfo = unwrap(data); + cbinfo->persistent_.Dispose(); + cbinfo->persistent_.Clear(); + cbinfo->callback_(*cbinfo); + delete cbinfo; +} + +template +WeakCallbackInfo *WeakCallbackInfo::unwrap( + NAN_WEAK_CALLBACK_DATA_TYPE_ data) { + WeakCallbackInfo *cbinfo = + static_cast*>(data); + cbinfo->isolate_ = v8::Isolate::GetCurrent(); + return cbinfo; +} + +#undef NAN_WEAK_CALLBACK_SIG_ +#undef NAN_WEAK_CALLBACK_DATA_TYPE_ +#endif + +#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \ + (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3)) +template +template +inline void Persistent::SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type) { + WeakCallbackInfo

*wcbd; + if (type == WeakCallbackType::kParameter) { + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , parameter); + v8::PersistentBase::SetWeak( + wcbd + , WeakCallbackInfo

::template invokeparameter + , type); + } else { + v8::Local* self_v(reinterpret_cast*>(this)); + assert((*self_v)->IsObject()); + v8::Local self((*self_v).As()); + int count = self->InternalFieldCount(); + void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0}; + for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) { + internal_fields[i] = self->GetAlignedPointerFromInternalField(i); + } + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , 0 + , internal_fields[0] + , internal_fields[1]); + self->SetAlignedPointerInInternalField(0, wcbd); + v8::PersistentBase::SetWeak( + static_cast*>(0) + , WeakCallbackInfo

::template invoketwofield + , type); + } +} +#elif NODE_MODULE_VERSION > IOJS_1_1_MODULE_VERSION +template +template +inline void Persistent::SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type) { + WeakCallbackInfo

*wcbd; + if (type == WeakCallbackType::kParameter) { + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , parameter); + v8::PersistentBase::SetPhantom( + wcbd + , WeakCallbackInfo

::invokeparameter); + } else { + v8::Local* self_v(reinterpret_cast*>(this)); + assert((*self_v)->IsObject()); + v8::Local self((*self_v).As()); + int count = self->InternalFieldCount(); + void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0}; + for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) { + internal_fields[i] = self->GetAlignedPointerFromInternalField(i); + } + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , 0 + , internal_fields[0] + , internal_fields[1]); + self->SetAlignedPointerInInternalField(0, wcbd); + v8::PersistentBase::SetPhantom( + static_cast*>(0) + , WeakCallbackInfo

::invoketwofield + , 0 + , count > 1 ? 1 : kNoInternalFieldIndex); + } +} +#elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION +template +template +inline void Persistent::SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type) { + WeakCallbackInfo

*wcbd; + if (type == WeakCallbackType::kParameter) { + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , parameter); + v8::PersistentBase::SetPhantom( + wcbd + , WeakCallbackInfo

::invokeparameter); + } else { + v8::Local* self_v(reinterpret_cast*>(this)); + assert((*self_v)->IsObject()); + v8::Local self((*self_v).As()); + int count = self->InternalFieldCount(); + void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0}; + for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) { + internal_fields[i] = self->GetAlignedPointerFromInternalField(i); + } + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , 0 + , internal_fields[0] + , internal_fields[1]); + self->SetAlignedPointerInInternalField(0, wcbd); + v8::PersistentBase::SetPhantom( + WeakCallbackInfo

::invoketwofield + , 0 + , count > 1 ? 1 : kNoInternalFieldIndex); + } +} +#elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION +template +template +inline void Persistent::SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type) { + WeakCallbackInfo

*wcbd; + if (type == WeakCallbackType::kParameter) { + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , parameter); + v8::PersistentBase::SetWeak(wcbd, WeakCallbackInfo

::invoke); + } else { + v8::Local* self_v(reinterpret_cast*>(this)); + assert((*self_v)->IsObject()); + v8::Local self((*self_v).As()); + int count = self->InternalFieldCount(); + void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0}; + for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) { + internal_fields[i] = self->GetAlignedPointerFromInternalField(i); + } + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , 0 + , internal_fields[0] + , internal_fields[1]); + v8::PersistentBase::SetWeak(wcbd, WeakCallbackInfo

::invoke); + } +} +#else +template +template +inline void PersistentBase::SetWeak( + P *parameter + , typename WeakCallbackInfo

::Callback callback + , WeakCallbackType type) { + WeakCallbackInfo

*wcbd; + if (type == WeakCallbackType::kParameter) { + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , parameter); + persistent.MakeWeak(wcbd, WeakCallbackInfo

::invoke); + } else { + v8::Local* self_v(reinterpret_cast*>(this)); + assert((*self_v)->IsObject()); + v8::Local self((*self_v).As()); + int count = self->InternalFieldCount(); + void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0}; + for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) { + internal_fields[i] = self->GetPointerFromInternalField(i); + } + wcbd = new WeakCallbackInfo

( + reinterpret_cast*>(this) + , callback + , 0 + , internal_fields[0] + , internal_fields[1]); + persistent.MakeWeak(wcbd, WeakCallbackInfo

::invoke); + } +} +#endif + +#endif // NAN_WEAK_H_ diff --git a/express-server/node_modules/nan/package.json b/express-server/node_modules/nan/package.json new file mode 100644 index 00000000..9e8d07f9 --- /dev/null +++ b/express-server/node_modules/nan/package.json @@ -0,0 +1,135 @@ +{ + "_args": [ + [ + "nan@^2.11.1", + "/nodeapps/https-test/greenlock-express.js/node_modules/ursa-optional" + ] + ], + "_from": "nan@>=2.11.1 <3.0.0", + "_hasShrinkwrap": false, + "_id": "nan@2.12.0", + "_inCache": true, + "_installable": true, + "_location": "/nan", + "_nodeVersion": "9.6.0", + "_npmOperationalInternal": { + "host": "s3://npm-registry-packages", + "tmp": "tmp/nan_2.12.0_1544966058111_0.3054513371345562" + }, + "_npmUser": { + "email": "bbyholm@abo.fi", + "name": "kkoopa" + }, + "_npmVersion": "5.6.0", + "_phantomChildren": {}, + "_requested": { + "name": "nan", + "raw": "nan@^2.11.1", + "rawSpec": "^2.11.1", + "scope": null, + "spec": ">=2.11.1 <3.0.0", + "type": "range" + }, + "_requiredBy": [ + "/ursa-optional" + ], + "_resolved": "https://registry.npmjs.org/nan/-/nan-2.12.0.tgz", + "_shasum": "9d443fdb5e13a20770cc5e602eee59760a685885", + "_shrinkwrap": null, + "_spec": "nan@^2.11.1", + "_where": "/nodeapps/https-test/greenlock-express.js/node_modules/ursa-optional", + "bugs": { + "url": "https://github.com/nodejs/nan/issues" + }, + "contributors": [ + { + "name": "Rod Vagg", + "email": "r@va.gg", + "url": "https://github.com/rvagg" + }, + { + "name": "Benjamin Byholm", + "email": "bbyholm@abo.fi", + "url": "https://github.com/kkoopa/" + }, + { + "name": "Trevor Norris", + "email": "trev.norris@gmail.com", + "url": "https://github.com/trevnorris" + }, + { + "name": "Nathan Rajlich", + "email": "nathan@tootallnate.net", + "url": "https://github.com/TooTallNate" + }, + { + "name": "Brett Lawson", + "email": "brett19@gmail.com", + "url": "https://github.com/brett19" + }, + { + "name": "Ben Noordhuis", + "email": "info@bnoordhuis.nl", + "url": "https://github.com/bnoordhuis" + }, + { + "name": "David Siegel", + "email": "david@artcom.de", + "url": "https://github.com/agnat" + }, + { + "name": "Michael Ira Krufky", + "email": "mkrufky@gmail.com", + "url": "https://github.com/mkrufky" + } + ], + "dependencies": {}, + "description": "Native Abstractions for Node.js: C++ header for Node 0.8 -> 11 compatibility", + "devDependencies": { + "bindings": "~1.2.1", + "commander": "^2.8.1", + "glob": "^5.0.14", + "node-gyp": "~3.6.2", + "readable-stream": "^2.1.4", + "request": "=2.81.0", + "tap": "~0.7.1", + "xtend": "~4.0.0" + }, + "directories": {}, + "dist": { + "fileCount": 46, + "integrity": "sha512-zT5nC0JhbljmyEf+Z456nvm7iO7XgRV2hYxoBtPpnyp+0Q4aCoP6uWNn76v/I6k2kCYNLWqWbwBWQcjsNI/bjw==", + "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcFk+qCRA9TVsSAnZWagAAKTYP/ifKNoarxTcvHhn31rYR\nU2Gr9fmUnNnakkjaUwsJofQvqrBJDMzmT5t0gbHSrFRsTr8Jx2WgmIotef84\njyZfNqI09UM2xHXOKqUiZTcQlAQ9VErtHi2PDWr/A1i1qv/3AGPxYRMpbWR1\nTgI2bC1YGAq87470BB41C0BRfEXd2c6DffBYFEgkWoyDiAHrSltNwziENf9B\nV05ovWxdIf3ugIpgSKPYms+ff+lM4G7AcdDmg5zHw1PwmUcMN4hNRFROD+dN\nWGpNzVCyEZ7aIa1iwOcMzRm8s0OtUCo+pxq/nzOB0Oo9jtuEkH/hwSZbw0OL\n/wY57CsIAkbDj8/QBLDfQRjOWJ7pINiaY9smRmZzFkGnr216ZhvYAPaFpzeQ\nV+ioAr8mXnlJVQcoo0EXBave1DWt7ucZm3y9Hc0HeE267sJQMkwDJnGZxFDE\ntSq4RZwT8Kjzl4fDmWWEisIJAoOCYvgzF0sYvCODbMOJ9NQtwt7X8ZzPnrkQ\nBuB8D7HtcsUPgPAglq+XbjxKRTx4HP3HnMWieLNwLrBWhJG6QG25eabMpoYC\nV0DeDFYx6YebK01kmAmnZ8uxx1uBScKD91FwxijkWfwSPakxrX97aocYFXJw\naOFtkc0/vf6p/o3cpXKNwZ5dALAiqU2qPENY6kEwsV6eyX4RzCSKQBKN+cbc\nW3aJ\r\n=bGq5\r\n-----END PGP SIGNATURE-----\r\n", + "shasum": "9d443fdb5e13a20770cc5e602eee59760a685885", + "tarball": "https://registry.npmjs.org/nan/-/nan-2.12.0.tgz", + "unpackedSize": 414432 + }, + "gitHead": "e8f8519db5f784b6b581b94d14bfe8df7cba91d2", + "homepage": "https://github.com/nodejs/nan#readme", + "license": "MIT", + "main": "include_dirs.js", + "maintainers": [ + { + "name": "kkoopa", + "email": "bbyholm@abo.fi" + }, + { + "name": "rvagg", + "email": "rod@vagg.org" + } + ], + "name": "nan", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/nodejs/nan.git" + }, + "scripts": { + "docs": "doc/.build.sh", + "rebuild-tests": "node-gyp rebuild --msvs_version=2015 --directory test", + "test": "tap --gc --stderr test/js/*-test.js", + "test:worker": "node --experimental-worker test/tap-as-worker.js --gc --stderr test/js/*-test.js" + }, + "version": "2.12.0" +} diff --git a/express-server/node_modules/nan/tools/1to2.js b/express-server/node_modules/nan/tools/1to2.js new file mode 100644 index 00000000..337f8bf2 --- /dev/null +++ b/express-server/node_modules/nan/tools/1to2.js @@ -0,0 +1,412 @@ +#!/usr/bin/env node +/********************************************************************* + * NAN - Native Abstractions for Node.js + * + * Copyright (c) 2018 NAN contributors + * + * MIT License + ********************************************************************/ + +var commander = require('commander'), + fs = require('fs'), + glob = require('glob'), + groups = [], + total = 0, + warning1 = '/* ERROR: Rewrite using Buffer */\n', + warning2 = '\\/\\* ERROR\\: Rewrite using Buffer \\*\\/\\n', + length, + i; + +fs.readFile(__dirname + '/package.json', 'utf8', function (err, data) { + if (err) { + throw err; + } + + commander + .version(JSON.parse(data).version) + .usage('[options] ') + .parse(process.argv); + + if (!process.argv.slice(2).length) { + commander.outputHelp(); + } +}); + +/* construct strings representing regular expressions + each expression contains a unique group allowing for identification of the match + the index of this key group, relative to the regular expression in question, + is indicated by the first array member */ + +/* simple substistutions, key group is the entire match, 0 */ +groups.push([0, [ + '_NAN_', + 'NODE_SET_METHOD', + 'NODE_SET_PROTOTYPE_METHOD', + 'NanAsciiString', + 'NanEscapeScope', + 'NanReturnValue', + 'NanUcs2String'].join('|')]); + +/* substitutions of parameterless macros, key group is 1 */ +groups.push([1, ['(', [ + 'NanEscapableScope', + 'NanReturnNull', + 'NanReturnUndefined', + 'NanScope'].join('|'), ')\\(\\)'].join('')]); + +/* replace TryCatch with NanTryCatch once, gobbling possible namespace, key group 2 */ +groups.push([2, '(?:(?:v8\\:\\:)?|(Nan)?)(TryCatch)']); + +/* NanNew("string") will likely not fail a ToLocalChecked(), key group 1 */ +groups.push([1, ['(NanNew)', '(\\("[^\\"]*"[^\\)]*\\))(?!\\.ToLocalChecked\\(\\))'].join('')]); + +/* Removed v8 APIs, warn that the code needs rewriting using node::Buffer, key group 2 */ +groups.push([2, ['(', warning2, ')?', '^.*?(', [ + 'GetIndexedPropertiesExternalArrayDataLength', + 'GetIndexedPropertiesExternalArrayData', + 'GetIndexedPropertiesExternalArrayDataType', + 'GetIndexedPropertiesPixelData', + 'GetIndexedPropertiesPixelDataLength', + 'HasIndexedPropertiesInExternalArrayData', + 'HasIndexedPropertiesInPixelData', + 'SetIndexedPropertiesToExternalArrayData', + 'SetIndexedPropertiesToPixelData'].join('|'), ')'].join('')]); + +/* No need for NanScope in V8-exposed methods, key group 2 */ +groups.push([2, ['((', [ + 'NAN_METHOD', + 'NAN_GETTER', + 'NAN_SETTER', + 'NAN_PROPERTY_GETTER', + 'NAN_PROPERTY_SETTER', + 'NAN_PROPERTY_ENUMERATOR', + 'NAN_PROPERTY_DELETER', + 'NAN_PROPERTY_QUERY', + 'NAN_INDEX_GETTER', + 'NAN_INDEX_SETTER', + 'NAN_INDEX_ENUMERATOR', + 'NAN_INDEX_DELETER', + 'NAN_INDEX_QUERY'].join('|'), ')\\([^\\)]*\\)\\s*\\{)\\s*NanScope\\(\\)\\s*;'].join('')]); + +/* v8::Value::ToXXXXXXX returns v8::MaybeLocal, key group 3 */ +groups.push([3, ['([\\s\\(\\)])([^\\s\\(\\)]+)->(', [ + 'Boolean', + 'Number', + 'String', + 'Object', + 'Integer', + 'Uint32', + 'Int32'].join('|'), ')\\('].join('')]); + +/* v8::Value::XXXXXXXValue returns v8::Maybe, key group 3 */ +groups.push([3, ['([\\s\\(\\)])([^\\s\\(\\)]+)->((?:', [ + 'Boolean', + 'Number', + 'Integer', + 'Uint32', + 'Int32'].join('|'), ')Value)\\('].join('')]); + +/* NAN_WEAK_CALLBACK macro was removed, write out callback definition, key group 1 */ +groups.push([1, '(NAN_WEAK_CALLBACK)\\(([^\\s\\)]+)\\)']); + +/* node::ObjectWrap and v8::Persistent have been replaced with Nan implementations, key group 1 */ +groups.push([1, ['(', [ + 'NanDisposePersistent', + 'NanObjectWrapHandle'].join('|'), ')\\s*\\(\\s*([^\\s\\)]+)'].join('')]); + +/* Since NanPersistent there is no need for NanMakeWeakPersistent, key group 1 */ +groups.push([1, '(NanMakeWeakPersistent)\\s*\\(\\s*([^\\s,]+)\\s*,\\s*']); + +/* Many methods of v8::Object and others now return v8::MaybeLocal, key group 3 */ +groups.push([3, ['([\\s])([^\\s]+)->(', [ + 'GetEndColumn', + 'GetFunction', + 'GetLineNumber', + 'NewInstance', + 'GetPropertyNames', + 'GetOwnPropertyNames', + 'GetSourceLine', + 'GetStartColumn', + 'ObjectProtoToString', + 'ToArrayIndex', + 'ToDetailString', + 'CallAsConstructor', + 'CallAsFunction', + 'CloneElementAt', + 'Delete', + 'ForceSet', + 'Get', + 'GetPropertyAttributes', + 'GetRealNamedProperty', + 'GetRealNamedPropertyInPrototypeChain', + 'Has', + 'HasOwnProperty', + 'HasRealIndexedProperty', + 'HasRealNamedCallbackProperty', + 'HasRealNamedProperty', + 'Set', + 'SetAccessor', + 'SetIndexedPropertyHandler', + 'SetNamedPropertyHandler', + 'SetPrototype'].join('|'), ')\\('].join('')]); + +/* You should get an error if any of these fail anyways, + or handle the error better, it is indicated either way, key group 2 */ +groups.push([2, ['NanNew(<(?:v8\\:\\:)?(', ['Date', 'String', 'RegExp'].join('|'), ')>)(\\([^\\)]*\\))(?!\\.ToLocalChecked\\(\\))'].join('')]); + +/* v8::Value::Equals now returns a v8::Maybe, key group 3 */ +groups.push([3, '([\\s\\(\\)])([^\\s\\(\\)]+)->(Equals)\\(([^\\s\\)]+)']); + +/* NanPersistent makes this unnecessary, key group 1 */ +groups.push([1, '(NanAssignPersistent)(?:]+>)?\\(([^,]+),\\s*']); + +/* args has been renamed to info, key group 2 */ +groups.push([2, '(\\W)(args)(\\W)']) + +/* node::ObjectWrap was replaced with NanObjectWrap, key group 2 */ +groups.push([2, '(\\W)(?:node\\:\\:)?(ObjectWrap)(\\W)']); + +/* v8::Persistent was replaced with NanPersistent, key group 2 */ +groups.push([2, '(\\W)(?:v8\\:\\:)?(Persistent)(\\W)']); + +/* counts the number of capturing groups in a well-formed regular expression, + ignoring non-capturing groups and escaped parentheses */ +function groupcount(s) { + var positive = s.match(/\((?!\?)/g), + negative = s.match(/\\\(/g); + return (positive ? positive.length : 0) - (negative ? negative.length : 0); +} + +/* compute the absolute position of each key group in the joined master RegExp */ +for (i = 1, length = groups.length; i < length; i++) { + total += groupcount(groups[i - 1][1]); + groups[i][0] += total; +} + +/* create the master RegExp, whis is the union of all the groups' expressions */ +master = new RegExp(groups.map(function (a) { return a[1]; }).join('|'), 'gm'); + +/* replacement function for String.replace, receives 21 arguments */ +function replace() { + /* simple expressions */ + switch (arguments[groups[0][0]]) { + case '_NAN_': + return 'NAN_'; + case 'NODE_SET_METHOD': + return 'NanSetMethod'; + case 'NODE_SET_PROTOTYPE_METHOD': + return 'NanSetPrototypeMethod'; + case 'NanAsciiString': + return 'NanUtf8String'; + case 'NanEscapeScope': + return 'scope.Escape'; + case 'NanReturnNull': + return 'info.GetReturnValue().SetNull'; + case 'NanReturnValue': + return 'info.GetReturnValue().Set'; + case 'NanUcs2String': + return 'v8::String::Value'; + default: + } + + /* macros without arguments */ + switch (arguments[groups[1][0]]) { + case 'NanEscapableScope': + return 'NanEscapableScope scope' + case 'NanReturnUndefined': + return 'return'; + case 'NanScope': + return 'NanScope scope'; + default: + } + + /* TryCatch, emulate negative backref */ + if (arguments[groups[2][0]] === 'TryCatch') { + return arguments[groups[2][0] - 1] ? arguments[0] : 'NanTryCatch'; + } + + /* NanNew("foo") --> NanNew("foo").ToLocalChecked() */ + if (arguments[groups[3][0]] === 'NanNew') { + return [arguments[0], '.ToLocalChecked()'].join(''); + } + + /* insert warning for removed functions as comment on new line above */ + switch (arguments[groups[4][0]]) { + case 'GetIndexedPropertiesExternalArrayData': + case 'GetIndexedPropertiesExternalArrayDataLength': + case 'GetIndexedPropertiesExternalArrayDataType': + case 'GetIndexedPropertiesPixelData': + case 'GetIndexedPropertiesPixelDataLength': + case 'HasIndexedPropertiesInExternalArrayData': + case 'HasIndexedPropertiesInPixelData': + case 'SetIndexedPropertiesToExternalArrayData': + case 'SetIndexedPropertiesToPixelData': + return arguments[groups[4][0] - 1] ? arguments[0] : [warning1, arguments[0]].join(''); + default: + } + + /* remove unnecessary NanScope() */ + switch (arguments[groups[5][0]]) { + case 'NAN_GETTER': + case 'NAN_METHOD': + case 'NAN_SETTER': + case 'NAN_INDEX_DELETER': + case 'NAN_INDEX_ENUMERATOR': + case 'NAN_INDEX_GETTER': + case 'NAN_INDEX_QUERY': + case 'NAN_INDEX_SETTER': + case 'NAN_PROPERTY_DELETER': + case 'NAN_PROPERTY_ENUMERATOR': + case 'NAN_PROPERTY_GETTER': + case 'NAN_PROPERTY_QUERY': + case 'NAN_PROPERTY_SETTER': + return arguments[groups[5][0] - 1]; + default: + } + + /* Value converstion */ + switch (arguments[groups[6][0]]) { + case 'Boolean': + case 'Int32': + case 'Integer': + case 'Number': + case 'Object': + case 'String': + case 'Uint32': + return [arguments[groups[6][0] - 2], 'NanTo(', arguments[groups[6][0] - 1]].join(''); + default: + } + + /* other value conversion */ + switch (arguments[groups[7][0]]) { + case 'BooleanValue': + return [arguments[groups[7][0] - 2], 'NanTo(', arguments[groups[7][0] - 1]].join(''); + case 'Int32Value': + return [arguments[groups[7][0] - 2], 'NanTo(', arguments[groups[7][0] - 1]].join(''); + case 'IntegerValue': + return [arguments[groups[7][0] - 2], 'NanTo(', arguments[groups[7][0] - 1]].join(''); + case 'Uint32Value': + return [arguments[groups[7][0] - 2], 'NanTo(', arguments[groups[7][0] - 1]].join(''); + default: + } + + /* NAN_WEAK_CALLBACK */ + if (arguments[groups[8][0]] === 'NAN_WEAK_CALLBACK') { + return ['template\nvoid ', + arguments[groups[8][0] + 1], '(const NanWeakCallbackInfo &data)'].join(''); + } + + /* use methods on NAN classes instead */ + switch (arguments[groups[9][0]]) { + case 'NanDisposePersistent': + return [arguments[groups[9][0] + 1], '.Reset('].join(''); + case 'NanObjectWrapHandle': + return [arguments[groups[9][0] + 1], '->handle('].join(''); + default: + } + + /* use method on NanPersistent instead */ + if (arguments[groups[10][0]] === 'NanMakeWeakPersistent') { + return arguments[groups[10][0] + 1] + '.SetWeak('; + } + + /* These return Maybes, the upper ones take no arguments */ + switch (arguments[groups[11][0]]) { + case 'GetEndColumn': + case 'GetFunction': + case 'GetLineNumber': + case 'GetOwnPropertyNames': + case 'GetPropertyNames': + case 'GetSourceLine': + case 'GetStartColumn': + case 'NewInstance': + case 'ObjectProtoToString': + case 'ToArrayIndex': + case 'ToDetailString': + return [arguments[groups[11][0] - 2], 'Nan', arguments[groups[11][0]], '(', arguments[groups[11][0] - 1]].join(''); + case 'CallAsConstructor': + case 'CallAsFunction': + case 'CloneElementAt': + case 'Delete': + case 'ForceSet': + case 'Get': + case 'GetPropertyAttributes': + case 'GetRealNamedProperty': + case 'GetRealNamedPropertyInPrototypeChain': + case 'Has': + case 'HasOwnProperty': + case 'HasRealIndexedProperty': + case 'HasRealNamedCallbackProperty': + case 'HasRealNamedProperty': + case 'Set': + case 'SetAccessor': + case 'SetIndexedPropertyHandler': + case 'SetNamedPropertyHandler': + case 'SetPrototype': + return [arguments[groups[11][0] - 2], 'Nan', arguments[groups[11][0]], '(', arguments[groups[11][0] - 1], ', '].join(''); + default: + } + + /* Automatic ToLocalChecked(), take it or leave it */ + switch (arguments[groups[12][0]]) { + case 'Date': + case 'String': + case 'RegExp': + return ['NanNew', arguments[groups[12][0] - 1], arguments[groups[12][0] + 1], '.ToLocalChecked()'].join(''); + default: + } + + /* NanEquals is now required for uniformity */ + if (arguments[groups[13][0]] === 'Equals') { + return [arguments[groups[13][0] - 1], 'NanEquals(', arguments[groups[13][0] - 1], ', ', arguments[groups[13][0] + 1]].join(''); + } + + /* use method on replacement class instead */ + if (arguments[groups[14][0]] === 'NanAssignPersistent') { + return [arguments[groups[14][0] + 1], '.Reset('].join(''); + } + + /* args --> info */ + if (arguments[groups[15][0]] === 'args') { + return [arguments[groups[15][0] - 1], 'info', arguments[groups[15][0] + 1]].join(''); + } + + /* ObjectWrap --> NanObjectWrap */ + if (arguments[groups[16][0]] === 'ObjectWrap') { + return [arguments[groups[16][0] - 1], 'NanObjectWrap', arguments[groups[16][0] + 1]].join(''); + } + + /* Persistent --> NanPersistent */ + if (arguments[groups[17][0]] === 'Persistent') { + return [arguments[groups[17][0] - 1], 'NanPersistent', arguments[groups[17][0] + 1]].join(''); + } + + /* This should not happen. A switch is probably missing a case if it does. */ + throw 'Unhandled match: ' + arguments[0]; +} + +/* reads a file, runs replacement and writes it back */ +function processFile(file) { + fs.readFile(file, {encoding: 'utf8'}, function (err, data) { + if (err) { + throw err; + } + + /* run replacement twice, might need more runs */ + fs.writeFile(file, data.replace(master, replace).replace(master, replace), function (err) { + if (err) { + throw err; + } + }); + }); +} + +/* process file names from command line and process the identified files */ +for (i = 2, length = process.argv.length; i < length; i++) { + glob(process.argv[i], function (err, matches) { + if (err) { + throw err; + } + matches.forEach(processFile); + }); +} diff --git a/express-server/node_modules/nan/tools/README.md b/express-server/node_modules/nan/tools/README.md new file mode 100644 index 00000000..7f07e4b8 --- /dev/null +++ b/express-server/node_modules/nan/tools/README.md @@ -0,0 +1,14 @@ +1to2 naively converts source code files from NAN 1 to NAN 2. There will be erroneous conversions, +false positives and missed opportunities. The input files are rewritten in place. Make sure that +you have backups. You will have to manually review the changes afterwards and do some touchups. + +```sh +$ tools/1to2.js + + Usage: 1to2 [options] + + Options: + + -h, --help output usage information + -V, --version output the version number +``` diff --git a/express-server/node_modules/nan/tools/package.json b/express-server/node_modules/nan/tools/package.json new file mode 100644 index 00000000..2dcdd789 --- /dev/null +++ b/express-server/node_modules/nan/tools/package.json @@ -0,0 +1,19 @@ +{ + "name": "1to2", + "version": "1.0.0", + "description": "NAN 1 -> 2 Migration Script", + "main": "1to2.js", + "repository": { + "type": "git", + "url": "git://github.com/nodejs/nan.git" + }, + "contributors": [ + "Benjamin Byholm (https://github.com/kkoopa/)", + "Mathias Küsel (https://github.com/mathiask88/)" + ], + "dependencies": { + "glob": "~5.0.10", + "commander": "~2.8.1" + }, + "license": "MIT" +} diff --git a/express-server/node_modules/pkijs/.gitattributes b/express-server/node_modules/pkijs/.gitattributes new file mode 100644 index 00000000..1ff0c423 --- /dev/null +++ b/express-server/node_modules/pkijs/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/express-server/node_modules/pkijs/.npmignore b/express-server/node_modules/pkijs/.npmignore new file mode 100644 index 00000000..297d8c11 --- /dev/null +++ b/express-server/node_modules/pkijs/.npmignore @@ -0,0 +1 @@ +/examples \ No newline at end of file diff --git a/express-server/node_modules/pkijs/LICENSE b/express-server/node_modules/pkijs/LICENSE new file mode 100644 index 00000000..4f71696a --- /dev/null +++ b/express-server/node_modules/pkijs/LICENSE @@ -0,0 +1,30 @@ +Copyright (c) 2014, GMO GlobalSign +Copyright (c) 2015, Peculiar Ventures +All rights reserved. + +Author 2014-2015, Yury Strozhevsky + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* 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. + +* Neither the name of the copyright holder 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. diff --git a/express-server/node_modules/pkijs/README.md b/express-server/node_modules/pkijs/README.md new file mode 100644 index 00000000..12d13074 --- /dev/null +++ b/express-server/node_modules/pkijs/README.md @@ -0,0 +1,287 @@ +# PKIjs + +[![license](https://img.shields.io/badge/license-BSD-green.svg?style=flat)](https://raw.githubusercontent.com/GlobalSign/PKI.js/master/LICENSE) + +Public Key Infrastructure (PKI) is the basis of how identity and key management is performed on the web today. PKIjs is a pure JavaScript library implementing the formats that are used in PKI applications. It is built on WebCrypto ([Web Cryptography API](http://www.w3.org/TR/WebCryptoAPI/)) and aspires to make it possible to build native web applications that utilize X.509 and the related formats on the web without plug-ins. + +## Introduction + +[PKIjs][] is a library made in order to help people deal with (sometimes) complicated world of PKI-related data. For the moment it is quite easy to create a simple signature but hard to create PKCS#7 encoded signature. Easy to read a X.509 certificate but hard to parse values within it. [PKIjs][] library will help all web applications (and chrome plug-ins) acomplish these and many other things. [PKIjs][] was designed in such a way to make it easy to extended by users through a use of layered internal structures. There are [**many examples**](https://github.com/GlobalSign/PKI.js/tree/master/examples) of using [PKIjs][] and the number of examples will grow. + +## Numbers behind the library + +* More than 25 000 lines of code and comments ([PKIjs][] library + [ASN1js][] library). +* More than 50 specialized pre-defined ASN.1 schemas. +* More than 50 specialized "helpers" working with almost all internal data (for example "GeneralName" type, all X.509 certificate extensions types, "revoked certificates" type, etc.). +* Everything that you need to work with all five major parts of PKI: X.509, PKCS#10, CMS, OCSP, Time-stamping. + +## Features of the library + +* First and **ONLY** (April 2015) open-source JS library with full support for all "Suite B" algorithms in CMS messages; +* First library with support for CMS Enveloped data (encrypt/decrypt) in pure JavaScript + Web Cryptography API; +* Fully object-oriented library. Inhiritence is using everywhere inside the lib; +* Working with HTML5 data objects (ArrayBuffer, Uint8Array, Promises, Web Cryptography API, etc.); +* Has a complete set of helpers for working with types like: + * GeneralName; + * RelativeDistinguishedName; + * Time; + * AlgorithmIdentifier; + * All types of ASN.1 strings, including "international" like UniversalString, UTF8String and BMPString (with help from [ASN1js][]); + * All extension types of X.509 certificates (BasicConstraints, CertificatePolicies, AuthorityKeyIdentifier etc.); + * All "support types" for OCSP requests and responces; + * All "support types" for Time-Stamping Protocol (TSP) requests and responces; +* **Has own certification chain verification engine, built in pure JavaScript, with help from Promises and Web Cryptography API latest standard implementation;** +* Working with **all** Web Cryptography API signature algorithms: + * RSASSA-PKCS1-v1_5; + * RSA-PSS; + * ECDSA; +* Working with **all** "Suite B" (and more) encryption algorithms and schemas: + * RSASSA-OAEP + AES-KW + AES-CBC/GCM; + * ECDH + KDF on SHA-1/256/384/512 + AES-KW + AES-CBC/GCM; + * Pre-defined "key encryption key" + AES-KW + AES-CBC/GCM; + * Password-based encryption for CMS with PBKDF2 on HMAC on SHA-1/256/384/512 + AES-KW + AES-CBC/GCM; +* Working with all major PKI-related types ("minor" types are not mentioned here but there are huge number of such "minor types"): + * X.509 certificates: + * Parsing internal values; + * Getting/setting any internal values; + * Creatiion of a new X.509 certificate "from scratch"; + * **Internal certificate chain validation engine**; + * X.509 "certificate revocation lists" (CRLs): + * Parsing internal values; + * Getting/setting any internal values; + * Creation of a new CRL "from scratch"; + * Validation of CRL signature; + * Search inside CRL for specific revoked certificate. + * PKCS#10 certificate request: + * Parsing internal values; + * Getting/setting any internal values; + * Creation of a new PKCS#10 certificate request "from scratch"; + * Validation of PKCS#10 signature; + * OCSP request: + * Parsing internal values; + * Getting/setting any internal values; + * Creation of a new OCSP request "from scratch". + * OCSP response: + * Parsing internal values; + * Getting/setting any internal values; + * Creation of a new OCSP response "from scratch"; + * Validation of OCSP response signature. + * Time-stamping request: + * Parsing internal values; + * Getting/setting any internal values; + * Creation of a new Time-stamping request "from scratch"; + * Validation of Time-stamping request signature; + * Time-stamping response: + * Parsing internal values; + * Getting/setting any internal values; + * Creation of a new Time-stamping response "from scratch"; + * Validation of Time-stamping response signature + * CMS Signed Data: + * Parsing internal values; + * Getting/setting any internal values; + * Creation of a new CMS Signed Data "from scratch"; + * Validation of CMS Signed Data signature; + * CMS Enveloped Data: + * Parsing internal values; + * Getting/setting any internal values; + * Creation (encryption) with full support for "Suite B" algorithms and more; + * Decryption with full support for "Suite B" algorithms and more; + * CMS Encrypted Data: + * Parsing internal values; + * Getting/setting any internal values; + * Creation (encryption) with password; + * Decryption with password; + * PKCS#12: + * Parsing internal values; + * Making any kind of internal values (SafeContexts/SafeBags) with any kind of parameters; + +## Examples + +```javascript + // #region Parsing raw data as a X.509 certificate object + var asn1 = org.pkijs.fromBER(buffer); + var cert_simpl = new org.pkijs.simpl.CERT({ schema: asn1.result }); + // #endregion +``` + +```javascript + // #region Creation of a new X.509 certificate + cert_simpl.serialNumber = new org.pkijs.asn1.INTEGER({ value: 1 }); + cert_simpl.issuer.types_and_values.push(new org.pkijs.simpl.ATTR_TYPE_AND_VALUE({ + type: "2.5.4.6", // Country name + value: new org.pkijs.asn1.PRINTABLESTRING({ value: "RU" }) + })); + cert_simpl.issuer.types_and_values.push(new org.pkijs.simpl.ATTR_TYPE_AND_VALUE({ + type: "2.5.4.3", // Common name + value: new org.pkijs.asn1.PRINTABLESTRING({ value: "Test" }) + })); + cert_simpl.subject.types_and_values.push(new org.pkijs.simpl.ATTR_TYPE_AND_VALUE({ + type: "2.5.4.6", // Country name + value: new org.pkijs.asn1.PRINTABLESTRING({ value: "RU" }) + })); + cert_simpl.subject.types_and_values.push(new org.pkijs.simpl.ATTR_TYPE_AND_VALUE({ + type: "2.5.4.3", // Common name + value: new org.pkijs.asn1.PRINTABLESTRING({ value: "Test" }) + })); + + cert_simpl.notBefore.value = new Date(2013, 01, 01); + cert_simpl.notAfter.value = new Date(2016, 01, 01); + + cert_simpl.extensions = new Array(); // Extensions are not a part of certificate by default, it's an optional array + + // #region "BasicConstraints" extension + var basic_constr = new org.pkijs.simpl.x509.BasicConstraints({ + cA: true, + pathLenConstraint: 3 + }); + + cert_simpl.extensions.push(new org.pkijs.simpl.EXTENSION({ + extnID: "2.5.29.19", + critical: false, + extnValue: basic_constr.toSchema().toBER(false), + parsedValue: basic_constr // Parsed value for well-known extensions + })); + // #endregion + + // #region "KeyUsage" extension + var bit_array = new ArrayBuffer(1); + var bit_view = new Uint8Array(bit_array); + + bit_view[0] = bit_view[0] | 0x02; // Key usage "cRLSign" flag + bit_view[0] = bit_view[0] | 0x04; // Key usage "keyCertSign" flag + + var key_usage = new org.pkijs.asn1.BITSTRING({ value_hex: bit_array }); + + cert_simpl.extensions.push(new org.pkijs.simpl.EXTENSION({ + extnID: "2.5.29.15", + critical: false, + extnValue: key_usage.toBER(false), + parsedValue: key_usage // Parsed value for well-known extensions + })); + // #endregion + // #endregion +``` + +```javascript + // #region Creation of a new CMS Signed Data + cms_signed_simpl = new org.pkijs.simpl.CMS_SIGNED_DATA({ + encapContentInfo: new org.pkijs.simpl.cms.EncapsulatedContentInfo({ + eContentType: "1.2.840.113549.1.7.1", // "data" content type + eContent: new org.pkijs.asn1.OCTETSTRING({ value_hex: buffer }) + }), + signerInfos: [ + new org.pkijs.simpl.CMS_SIGNER_INFO({ + sid: new org.pkijs.simpl.cms.IssuerAndSerialNumber({ + issuer: cert_simpl.issuer, + serialNumber: cert_simpl.serialNumber + }) + }) + ], + certificates: [cert_simpl] + }); + + return cms_signed_simpl.sign(privateKey, 0, hashAlgorithm); + // #endregion + +``` + +More examples could be found in [**"examples" folder**](https://github.com/GlobalSign/PKI.js/tree/master/examples). Live example can be found at [pkijs.org](https://pkijs.org). + +## Limitations + +* Does not work with Internet Explorer's implementation of Web Cryptography API it is based on a old draft and also does not support all needed capabilities. +* Does not work with PolyCrypt it is based on a old version of Web Cryptography API and is buggy. +* You can use [PKIjs][] in almost all browsers. Please check [this page](http://caniuse.com/#feat=cryptography) for information about Web Cryptography API browser support. + +## Suitability +At this time this library should be considered suitable for research and experimentation, futher code and security review is needed before utilization in a production application. + +## Bug Reporting +Please report bugs either as pull requests or as issues in the issue tracker. PKIjs has a full disclosure vulnerability policy. Please do NOT attempt to report any security vulnerability in this code privately to anybody. + +## Related source code + +* [ASN1js project](https://github.com/GlobalSign/ASN1.js) - in fact [PKIjs][] will not work without [ASN1js][], it's neccessary part of the [PKIjs][] project; +* [C++ ASN1:2008 BER coder/decoder](https://github.com/YuryStrozhevsky/C-plus-plus-ASN.1-2008-coder-decoder) - the "father" of [ASN1js][] project; +* [Freely available ASN.1:2008 test suite](https://github.com/YuryStrozhevsky/ASN1-2008-free-test-suite) - the suite which can help you to validate (and better understand) any ASN.1 coder/decoder; + +## How to use PKIjs with Node.js + +**!!! WARNING !!!** +**Currently there is no "polyfill" of Web Cryptography API in Node.js. Thus you will not be able to use signature / verification features of PKIjs in Node.js programs.** + +In order to use PKIjs you will also need [ASN1js][] plus [node.extend](https://www.npmjs.com/package/node.extend) package. +```javascript + var merge = require("node.extend"); + + var common = require("asn1js/org/pkijs/common"); + var _asn1js = require("asn1js"); + var _pkijs = require("pkijs"); + var _x509schema = require("pkijs/org/pkijs/x509_schema"); + + // #region Merging function/object declarations for ASN1js and PKIjs + var asn1js = merge(true, _asn1js, common); + + var x509schema = merge(true, _x509schema, asn1js); + + var pkijs_1 = merge(true, _pkijs, asn1js); + var pkijs = merge(true, pkijs_1, x509schema); + // #endregion +``` + +After that you will ba able to use ASN1js and PKIjs via common way: +```javascript + // #region Decode and parse X.509 cert + var asn1 = pkijs.org.pkijs.fromBER(certBuffer); + var cert; + try + { + cert = new pkijs.org.pkijs.simpl.CERT({ schema: asn1.result }); + } + catch(ex) + { + return; + } + // #endregion +``` + +## License + +Copyright (c) 2014, [GMO GlobalSign](http://www.globalsign.com/) +Copyright (c) 2015, [Peculiar Ventures](http://peculiarventures.com/) +All rights reserved. + +Author 2014-2015, [Yury Strozhevsky](http://www.strozhevsky.com/). + +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 copyright holder 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. + + +[ASN.1]: http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One +[ASN1js]: http://asn1js.org/ +[PKIjs]: http://pkijs.org/ +[BER]: http://en.wikipedia.org/wiki/X.690#BER_encoding +[DER]: http://en.wikipedia.org/wiki/X.690#DER_encoding +[freely available ASN.1:2008 test suite]: http://www.strozhevsky.com/free_docs/free_asn1_testsuite_descr.pdf diff --git a/express-server/node_modules/pkijs/org/pkijs/cms_schema.js b/express-server/node_modules/pkijs/org/pkijs/cms_schema.js new file mode 100644 index 00000000..051b484d --- /dev/null +++ b/express-server/node_modules/pkijs/org/pkijs/cms_schema.js @@ -0,0 +1,1259 @@ +/* + * Copyright (c) 2014, GMO GlobalSign + * Copyright (c) 2015, Peculiar Ventures + * All rights reserved. + * + * Author 2014-2015, Yury Strozhevsky . + * + * 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 copyright holder 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. + * + */ +( +function(in_window) +{ + //************************************************************************************** + // #region Declaration of global variables + //************************************************************************************** + // #region "org" namespace + if(typeof in_window.org === "undefined") + in_window.org = {}; + else + { + if(typeof in_window.org !== "object") + throw new Error("Name org already exists and it's not an object"); + } + // #endregion + + // #region "org.pkijs" namespace + if(typeof in_window.org.pkijs === "undefined") + in_window.org.pkijs = {}; + else + { + if(typeof in_window.org.pkijs !== "object") + throw new Error("Name org.pkijs already exists and it's not an object" + " but " + (typeof in_window.org.pkijs)); + } + // #endregion + + // #region "org.pkijs.schema" namespace + if(typeof in_window.org.pkijs.schema === "undefined") + in_window.org.pkijs.schema = {}; + else + { + if(typeof in_window.org.pkijs.schema !== "object") + throw new Error("Name org.pkijs.schema already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.schema)); + } + // #endregion + + // #region "org.pkijs.schema.cms" namespace + if(typeof in_window.org.pkijs.schema.cms === "undefined") + in_window.org.pkijs.schema.cms = {}; + else + { + if(typeof in_window.org.pkijs.schema.cms !== "object") + throw new Error("Name org.pkijs.schema.cms already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.schema.cms)); + } + // #endregion + + // #region "local" namespace + var local = {}; + // #endregion + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "ContentInfo" type (RFC5652) + //************************************************************************************** + in_window.org.pkijs.schema.CMS_CONTENT_INFO = + function(input_args, optional) + { + //ContentInfo ::= SEQUENCE { + // contentType ContentType, + // content [0] EXPLICIT ANY DEFINED BY contentType } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + if(typeof optional === "undefined") + optional = false; + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || "ContentInfo"), + optional: optional, + value: [ + new in_window.org.pkijs.asn1.OID({ name: (names.contentType || "contentType") }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [new in_window.org.pkijs.asn1.ANY({ name: (names.content || "content") })] // EXPLICIT ANY value + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema for CMS "CertificateSet" type + //************************************************************************************** + in_window.org.pkijs.schema.cms.OtherCertificateFormat = + function() + { + //OtherCertificateFormat ::= SEQUENCE { + // otherCertFormat OBJECT IDENTIFIER, + // otherCert ANY DEFINED BY otherCertFormat } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.OID({ name: (names.otherCertFormat || "otherCertFormat") }), + new in_window.org.pkijs.asn1.ANY({ name: (names.otherCert || "otherCert") }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.CMS_CERTIFICATE_SET = + function() + { + //CertificateSet ::= SET OF CertificateChoices + // + //CertificateChoices ::= CHOICE { + // certificate Certificate, + // extendedCertificate [0] IMPLICIT ExtendedCertificate, -- Obsolete + // v1AttrCert [1] IMPLICIT AttributeCertificateV1, -- Obsolete + // v2AttrCert [2] IMPLICIT AttributeCertificateV2, + // other [3] IMPLICIT OtherCertificateFormat } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return ( + new in_window.org.pkijs.asn1.SET({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.certificates || ""), + value: new in_window.org.pkijs.asn1.CHOICE({ + value: [ + in_window.org.pkijs.schema.CERT(), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [ + new in_window.org.pkijs.asn1.ANY() + ] + }), // JUST A STUB + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 2 // [2] + }, + value: [ + new in_window.org.pkijs.asn1.ANY() + ] + }), // JUST A STUB + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 3 // [3] + }, + value: [ + new in_window.org.pkijs.asn1.OID(), + new in_window.org.pkijs.asn1.ANY() + ] + }) + ] + }) + }) + ] + }) + ); // TODO: Add definition for "AttributeCertificateV2" + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema for CMS "RevocationInfoChoices" type + //************************************************************************************** + in_window.org.pkijs.schema.cms.OtherRevocationInfoFormat = + function() + { + //OtherCertificateFormat ::= SEQUENCE { + // otherRevInfoFormat OBJECT IDENTIFIER, + // otherRevInfo ANY DEFINED BY otherCertFormat } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.OID({ name: (names.otherRevInfoFormat || "otherRevInfoFormat") }), + new in_window.org.pkijs.asn1.ANY({ name: (names.otherRevInfo || "otherRevInfo") }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.CMS_REVOCATION_INFO_CHOICES = + function() + { + //RevocationInfoChoices ::= SET OF RevocationInfoChoice + + //RevocationInfoChoice ::= CHOICE { + // crl CertificateList, + // other [1] IMPLICIT OtherRevocationInfoFormat } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SET({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.crls || ""), + value: new in_window.org.pkijs.asn1.CHOICE({ + value: [ + in_window.org.pkijs.schema.CRL(), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [ + new in_window.org.pkijs.asn1.OID(), + new in_window.org.pkijs.asn1.ANY() + ] + }) + ] + }) + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema for CMS "IssuerAndSerialNumber" type + //************************************************************************************** + in_window.org.pkijs.schema.cms.IssuerAndSerialNumber = + function() + { + //IssuerAndSerialNumber ::= SEQUENCE { + // issuer Name, + // serialNumber CertificateSerialNumber } + // + //CertificateSerialNumber ::= INTEGER + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + in_window.org.pkijs.schema.RDN(names.issuer || {}), + new in_window.org.pkijs.asn1.INTEGER({ name: (names.serialNumber || "") }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema for CMS "Attribute" type + //************************************************************************************** + in_window.org.pkijs.schema.cms.Attribute = + function() + { + //Attribute ::= SEQUENCE { + // attrType OBJECT IDENTIFIER, + // attrValues SET OF AttributeValue } + + //AttributeValue ::= ANY + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.OID({ name: (names.attrType || "") }), + new in_window.org.pkijs.asn1.SET({ + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.attrValues || ""), + value: new in_window.org.pkijs.asn1.ANY() + }) + ] + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "RSAES-OAEP-params" type (RFC3447) + //************************************************************************************** + in_window.org.pkijs.schema.cms.RSAES_OAEP_params = + function() + { + //RSAES-OAEP-params ::= SEQUENCE { + // hashAlgorithm [0] HashAlgorithm DEFAULT sha1, + // maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1, + // pSourceAlgorithm [2] PSourceAlgorithm DEFAULT pSpecifiedEmpty + //} + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + optional: true, + value: [in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.hashAlgorithm || {})] + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + optional: true, + value: [in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.maskGenAlgorithm || {})] + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 2 // [2] + }, + optional: true, + value: [in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.pSourceAlgorithm || {})] + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema for CMS "SignedAttributes" and "UnsignedAttributes" types + //************************************************************************************** + in_window.org.pkijs.schema.cms.SignedUnsignedAttributes = + function(input_args, input_tag_number) + { + // signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL, + // unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL } + + //SignedAttributes ::= SET SIZE (1..MAX) OF Attribute + + //UnsignedAttributes ::= SET SIZE (1..MAX) OF Attribute + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + name: (names.block_name || ""), + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: input_tag_number // "SignedAttributes" = 0, "UnsignedAttributes" = 1 + }, + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.attributes || ""), + value: in_window.org.pkijs.schema.cms.Attribute() + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for CMS "SignerInfo" type + //************************************************************************************** + in_window.org.pkijs.schema.CMS_SIGNER_INFO = + function() + { + //SignerInfo ::= SEQUENCE { + // version CMSVersion, + // sid SignerIdentifier, + // digestAlgorithm DigestAlgorithmIdentifier, + // signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL, + // signatureAlgorithm SignatureAlgorithmIdentifier, + // signature SignatureValue, + // unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL } + // + //SignerIdentifier ::= CHOICE { + // issuerAndSerialNumber IssuerAndSerialNumber, + // subjectKeyIdentifier [0] SubjectKeyIdentifier } + // + //SubjectKeyIdentifier ::= OCTET STRING + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return ( + new in_window.org.pkijs.asn1.SEQUENCE({ + name: "SignerInfo", + value: [ + new in_window.org.pkijs.asn1.INTEGER({ name: (names.version || "SignerInfo.version") }), + new in_window.org.pkijs.asn1.CHOICE({ + value: [ + in_window.org.pkijs.schema.cms.IssuerAndSerialNumber(names.sid || { + names: { + block_name: "SignerInfo.sid" + } + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + name: (names.sid || "SignerInfo.sid"), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [new in_window.org.pkijs.asn1.OCTETSTRING()] + }) + ] + }), + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.digestAlgorithm || { + names: { + block_name: "SignerInfo.digestAlgorithm" + } + }), + in_window.org.pkijs.schema.cms.SignedUnsignedAttributes(names.signedAttrs || { + names: { + block_name: "SignerInfo.signedAttrs" + } + }, 0), + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.signatureAlgorithm || { + names: { + block_name: "SignerInfo.signatureAlgorithm" + } + }), + new in_window.org.pkijs.asn1.OCTETSTRING({ name: (names.signature || "SignerInfo.signature") }), + in_window.org.pkijs.schema.cms.SignedUnsignedAttributes(names.unsignedAttrs || { + names: { + block_name: "SignerInfo.unsignedAttrs" + } + }, 1) + ] + }) + ); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema for CMS "EncapsulatedContentInfo" type + //************************************************************************************** + in_window.org.pkijs.schema.cms.EncapsulatedContentInfo = + function() + { + //EncapsulatedContentInfo ::= SEQUENCE { + // eContentType ContentType, + // eContent [0] EXPLICIT OCTET STRING OPTIONAL } // Changed it to ANY, as in PKCS#7 + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.OID({ name: (names.eContentType || "") }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [ + new in_window.org.pkijs.asn1.ANY({ name: (names.eContent || "") }) // In order to aling this with PKCS#7 and CMS as well + ] + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "SignedData" type (RFC5652) + //************************************************************************************** + in_window.org.pkijs.schema.CMS_SIGNED_DATA = + function(names, optional_flag) + { + //SignedData ::= SEQUENCE { + // version CMSVersion, + // digestAlgorithms DigestAlgorithmIdentifiers, + // encapContentInfo EncapsulatedContentInfo, + // certificates [0] IMPLICIT CertificateSet OPTIONAL, + // crls [1] IMPLICIT RevocationInfoChoices OPTIONAL, + // signerInfos SignerInfos } + + names = in_window.org.pkijs.getNames(arguments[0]); + + if(typeof optional_flag === "undefined") + optional_flag = false; + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || "SignedData"), + optional: optional_flag, + value: [ + new in_window.org.pkijs.asn1.INTEGER({ name: (names.version || "SignedData.version") }), + new in_window.org.pkijs.asn1.SET({ + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.digestAlgorithms || "SignedData.digestAlgorithms"), + value: in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER() + }) + ] + }), + in_window.org.pkijs.schema.cms.EncapsulatedContentInfo(names.encapContentInfo || { + names: { + block_name: "SignedData.encapContentInfo" + } + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: in_window.org.pkijs.schema.CMS_CERTIFICATE_SET(names.certificates || { + names: { + certificates: "SignedData.certificates" + } + }).value_block.value + }), // IMPLICIT CertificateSet + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: in_window.org.pkijs.schema.CMS_REVOCATION_INFO_CHOICES(names.crls || { + names: { + crls: "SignedData.crls" + } + }).value_block.value + }), // IMPLICIT RevocationInfoChoices + new in_window.org.pkijs.asn1.SET({ + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.signerInfos || "SignedData.signerInfos"), + value: in_window.org.pkijs.schema.CMS_SIGNER_INFO() + }) + ] + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema for CMS "ECC-CMS-SharedInfo" type (RFC5753) + //************************************************************************************** + in_window.org.pkijs.schema.cms.ECC_CMS_SharedInfo = + function() + { + //ECC-CMS-SharedInfo ::= SEQUENCE { + // keyInfo AlgorithmIdentifier, + // entityUInfo [0] EXPLICIT OCTET STRING OPTIONAL, + // suppPubInfo [2] EXPLICIT OCTET STRING } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.keyInfo || {}), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + name: (names.entityUInfo || ""), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + optional: true, + value: [new in_window.org.pkijs.asn1.OCTETSTRING()] + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + name: (names.suppPubInfo || ""), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 2 // [2] + }, + value: [new in_window.org.pkijs.asn1.OCTETSTRING()] + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema for CMS "PBKDF2-params" type (RFC2898) + //************************************************************************************** + in_window.org.pkijs.schema.cms.PBKDF2_params = + function() + { + //PBKDF2-params ::= SEQUENCE { + // salt CHOICE { + // specified OCTET STRING, + // otherSource AlgorithmIdentifier }, + // iterationCount INTEGER (1..MAX), + // keyLength INTEGER (1..MAX) OPTIONAL, + // prf AlgorithmIdentifier + // DEFAULT { algorithm hMAC-SHA1, parameters NULL } } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.CHOICE({ + value: [ + new in_window.org.pkijs.asn1.OCTETSTRING({ name: (names.salt_primitive || "") }), + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.salt_constructed || {}) + ] + }), + new in_window.org.pkijs.asn1.INTEGER({ name: (names.iterationCount || "") }), + new in_window.org.pkijs.asn1.INTEGER({ + name: (names.keyLength || ""), + optional: true + }), + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.prf || { + names: { + optional: true + } + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema for CMS "PBES2-params" type (RFC2898) + //************************************************************************************** + in_window.org.pkijs.schema.cms.PBES2_params = + function() + { + //PBES2-params ::= SEQUENCE { + // keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, + // encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.keyDerivationFunc || {}), + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.encryptionScheme || {}) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "RecipientInfo" type (RFC5652) + //************************************************************************************** + in_window.org.pkijs.schema.cms.RecipientIdentifier = + function() + { + //RecipientIdentifier ::= CHOICE { + // issuerAndSerialNumber IssuerAndSerialNumber, + // subjectKeyIdentifier [0] SubjectKeyIdentifier } + // + //SubjectKeyIdentifier ::= OCTET STRING + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.CHOICE({ + value: [ + in_window.org.pkijs.schema.cms.IssuerAndSerialNumber({ + names: { + block_name: (names.block_name || "") + } + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + name: (names.block_name || ""), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [new in_window.org.pkijs.asn1.OCTETSTRING()] + }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.cms.KeyTransRecipientInfo = + function() + { + //KeyTransRecipientInfo ::= SEQUENCE { + // version CMSVersion, -- always set to 0 or 2 + // rid RecipientIdentifier, + // keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, + // encryptedKey EncryptedKey } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.INTEGER({ name: (names.version || "") }), + in_window.org.pkijs.schema.cms.RecipientIdentifier(names.rid || {}), + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.keyEncryptionAlgorithm || {}), + new in_window.org.pkijs.asn1.OCTETSTRING({ name: (names.encryptedKey || "") }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.cms.OriginatorPublicKey = + function() + { + //OriginatorPublicKey ::= SEQUENCE { + // algorithm AlgorithmIdentifier, + // publicKey BIT STRING } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.algorithm || {}), + new in_window.org.pkijs.asn1.BITSTRING({ name: (names.publicKey || "") }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.cms.OriginatorIdentifierOrKey = + function() + { + //OriginatorIdentifierOrKey ::= CHOICE { + // issuerAndSerialNumber IssuerAndSerialNumber, + // subjectKeyIdentifier [0] SubjectKeyIdentifier, + // originatorKey [1] OriginatorPublicKey } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.CHOICE({ + value: [ + in_window.org.pkijs.schema.cms.IssuerAndSerialNumber({ + names: { + block_name: (names.block_name || "") + } + }), + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + name: (names.block_name || "") + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + name: (names.block_name || ""), + value: in_window.org.pkijs.schema.cms.OriginatorPublicKey().value_block.value + }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.cms.OtherKeyAttribute = + function() + { + //OtherKeyAttribute ::= SEQUENCE { + // keyAttrId OBJECT IDENTIFIER, + // keyAttr ANY DEFINED BY keyAttrId OPTIONAL } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + optional: (names.optional || true), + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.OID({ name: (names.keyAttrId || "") }), + new in_window.org.pkijs.asn1.ANY({ + optional: true, + name: (names.keyAttr || "") + }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.cms.RecipientKeyIdentifier = + function() + { + //RecipientKeyIdentifier ::= SEQUENCE { + // subjectKeyIdentifier SubjectKeyIdentifier, + // date GeneralizedTime OPTIONAL, + // other OtherKeyAttribute OPTIONAL } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.OCTETSTRING({ name: (names.subjectKeyIdentifier || "") }), + new in_window.org.pkijs.asn1.GENERALIZEDTIME({ + optional: true, + name: (names.date || "") + }), + in_window.org.pkijs.schema.cms.OtherKeyAttribute(names.other || {}) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.cms.KeyAgreeRecipientIdentifier = + function() + { + //KeyAgreeRecipientIdentifier ::= CHOICE { + // issuerAndSerialNumber IssuerAndSerialNumber, + // rKeyId [0] IMPLICIT RecipientKeyIdentifier } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.CHOICE({ + value: [ + in_window.org.pkijs.schema.cms.IssuerAndSerialNumber(names.issuerAndSerialNumber || { + names: { + block_name: (names.block_name || "") + } + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + name: (names.block_name || ""), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: in_window.org.pkijs.schema.cms.RecipientKeyIdentifier(names.rKeyId || { + names: { + block_name: (names.block_name || "") + } + }).value_block.value + }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.cms.RecipientEncryptedKey = + function() + { + //RecipientEncryptedKey ::= SEQUENCE { + // rid KeyAgreeRecipientIdentifier, + // encryptedKey EncryptedKey } + // + //EncryptedKey ::= OCTET STRING + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + in_window.org.pkijs.schema.cms.KeyAgreeRecipientIdentifier(names.rid || {}), + new in_window.org.pkijs.asn1.OCTETSTRING({ name: (names.encryptedKey || "") }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.cms.RecipientEncryptedKeys = + function() + { + //RecipientEncryptedKeys ::= SEQUENCE OF RecipientEncryptedKey + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.RecipientEncryptedKeys || ""), + value: in_window.org.pkijs.schema.cms.RecipientEncryptedKey() + }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.cms.KeyAgreeRecipientInfo = + function() + { + //KeyAgreeRecipientInfo ::= SEQUENCE { + // version CMSVersion, -- always set to 3 + // originator [0] EXPLICIT OriginatorIdentifierOrKey, + // ukm [1] EXPLICIT UserKeyingMaterial OPTIONAL, + // keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, + // recipientEncryptedKeys RecipientEncryptedKeys } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: names.block_name || "", + value: [ + new in_window.org.pkijs.asn1.INTEGER({ name: names.version || "" }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [ + in_window.org.pkijs.schema.cms.OriginatorIdentifierOrKey(names.originator || {}) + ] + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [new in_window.org.pkijs.asn1.OCTETSTRING({ name: names.ukm || "" })] + }), + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.keyEncryptionAlgorithm || {}), + in_window.org.pkijs.schema.cms.RecipientEncryptedKeys(names.recipientEncryptedKeys || {}) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.cms.KEKIdentifier = + function() + { + //KEKIdentifier ::= SEQUENCE { + // keyIdentifier OCTET STRING, + // date GeneralizedTime OPTIONAL, + // other OtherKeyAttribute OPTIONAL } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.OCTETSTRING({ name: (names.keyIdentifier || "") }), + new in_window.org.pkijs.asn1.GENERALIZEDTIME({ + optional: true, + name: (names.date || "") + }), + in_window.org.pkijs.schema.cms.OtherKeyAttribute(names.other || {}) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.cms.KEKRecipientInfo = + function() + { + //KEKRecipientInfo ::= SEQUENCE { + // version CMSVersion, -- always set to 4 + // kekid KEKIdentifier, + // keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, + // encryptedKey EncryptedKey } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.INTEGER({ name: (names.version || "") }), + in_window.org.pkijs.schema.cms.KEKIdentifier(names.kekid || {}), + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.keyEncryptionAlgorithm || {}), + new in_window.org.pkijs.asn1.OCTETSTRING({ name: (names.encryptedKey || "") }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.cms.PasswordRecipientinfo = + function() + { + //PasswordRecipientInfo ::= SEQUENCE { + // version CMSVersion, -- Always set to 0 + // keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier OPTIONAL, + // keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, + // encryptedKey EncryptedKey } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.INTEGER({ name: (names.version || "") }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + name: (names.keyDerivationAlgorithm || ""), + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER().value_block.value + }), + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.keyEncryptionAlgorithm || {}), + new in_window.org.pkijs.asn1.OCTETSTRING({ name: (names.encryptedKey || "") }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.cms.OtherRecipientInfo = + function() + { + //OtherRecipientInfo ::= SEQUENCE { + // oriType OBJECT IDENTIFIER, + // oriValue ANY DEFINED BY oriType } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.OID({ name: (names.oriType || "") }), + new in_window.org.pkijs.asn1.ANY({ name: (names.oriValue || "") }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.CMS_RECIPIENT_INFO = + function() + { + //RecipientInfo ::= CHOICE { + // ktri KeyTransRecipientInfo, + // kari [1] KeyAgreeRecipientInfo, + // kekri [2] KEKRecipientInfo, + // pwri [3] PasswordRecipientinfo, + // ori [4] OtherRecipientInfo } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.CHOICE({ + value: [ + in_window.org.pkijs.schema.cms.KeyTransRecipientInfo({ + names: { + block_name: (names.block_name || "") + } + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + name: (names.block_name || ""), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: in_window.org.pkijs.schema.cms.KeyAgreeRecipientInfo().value_block.value + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + name: (names.block_name || ""), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 2 // [2] + }, + value: in_window.org.pkijs.schema.cms.KEKRecipientInfo().value_block.value + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + name: (names.block_name || ""), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 3 // [3] + }, + value: in_window.org.pkijs.schema.cms.PasswordRecipientinfo().value_block.value + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + name: (names.block_name || ""), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 4 // [4] + }, + value: in_window.org.pkijs.schema.cms.OtherRecipientInfo().value_block.value + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "EnvelopedData" type (RFC5652) + //************************************************************************************** + in_window.org.pkijs.schema.cms.OriginatorInfo = + function() + { + //OriginatorInfo ::= SEQUENCE { + // certs [0] IMPLICIT CertificateSet OPTIONAL, + // crls [1] IMPLICIT RevocationInfoChoices OPTIONAL } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + name: (names.certs || ""), + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: in_window.org.pkijs.schema.CMS_CERTIFICATE_SET().value_block.value + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + name: (names.crls || ""), + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: in_window.org.pkijs.schema.CMS_REVOCATION_INFO_CHOICES().value_block.value + }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.cms.EncryptedContentInfo = + function() + { + //EncryptedContentInfo ::= SEQUENCE { + // contentType ContentType, + // contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, + // encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL } + // + // Comment: Strange, but modern crypto engines create "encryptedContent" as "[0] EXPLICIT EncryptedContent" + // + //EncryptedContent ::= OCTET STRING + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.OID({ name: (names.contentType || "") }), + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.contentEncryptionAlgorithm || {}), + // The CHOICE we need because "EncryptedContent" could have either "constructive" + // or "primitive" form of encoding and we need to handle both variants + new in_window.org.pkijs.asn1.CHOICE({ + value: [ + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + name: (names.encryptedContent || ""), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + value: new in_window.org.pkijs.asn1.OCTETSTRING() + }) + ] + }), + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + name: (names.encryptedContent || ""), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + } + }) + ] + }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.CMS_ENVELOPED_DATA = + function() + { + //EnvelopedData ::= SEQUENCE { + // version CMSVersion, + // originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, + // recipientInfos RecipientInfos, + // encryptedContentInfo EncryptedContentInfo, + // unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.INTEGER({ name: (names.version || "") }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + name: (names.originatorInfo || ""), + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: in_window.org.pkijs.schema.cms.OriginatorInfo().value_block.value + }), + new in_window.org.pkijs.asn1.SET({ + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.recipientInfos || ""), + value: in_window.org.pkijs.schema.CMS_RECIPIENT_INFO() + }) + ] + }), + in_window.org.pkijs.schema.cms.EncryptedContentInfo(names.encryptedContentInfo || {}), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.unprotectedAttrs || ""), + value: in_window.org.pkijs.schema.ATTRIBUTE() + }) + ] + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "EncryptedData" type (RFC5652) + //************************************************************************************** + in_window.org.pkijs.schema.CMS_ENCRYPTED_DATA = + function() + { + //id-encryptedData OBJECT IDENTIFIER ::= { iso(1) member-body(2) + // us(840) rsadsi(113549) pkcs(1) pkcs7(7) 6 } + + //EncryptedData ::= SEQUENCE { + // version CMSVersion, + // encryptedContentInfo EncryptedContentInfo, + // unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.INTEGER({ name: (names.version || "") }), + in_window.org.pkijs.schema.cms.EncryptedContentInfo(names.encryptedContentInfo || {}), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.unprotectedAttrs || ""), + value: in_window.org.pkijs.schema.ATTRIBUTE() + }) + ] + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** +} +)(typeof exports !== "undefined" ? exports : window); \ No newline at end of file diff --git a/express-server/node_modules/pkijs/org/pkijs/cms_simpl.js b/express-server/node_modules/pkijs/org/pkijs/cms_simpl.js new file mode 100644 index 00000000..69237a22 --- /dev/null +++ b/express-server/node_modules/pkijs/org/pkijs/cms_simpl.js @@ -0,0 +1,6933 @@ +/* + * Copyright (c) 2014, GMO GlobalSign + * Copyright (c) 2015, Peculiar Ventures + * All rights reserved. + * + * Author 2014-2015, Yury Strozhevsky . + * + * 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 copyright holder 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. + * + */ +( +function(in_window) +{ + //************************************************************************************** + // #region Declaration of global variables + //************************************************************************************** + // #region "org" namespace + if(typeof in_window.org === "undefined") + in_window.org = {}; + else + { + if(typeof in_window.org !== "object") + throw new Error("Name org already exists and it's not an object"); + } + // #endregion + + // #region "org.pkijs" namespace + if(typeof in_window.org.pkijs === "undefined") + in_window.org.pkijs = {}; + else + { + if(typeof in_window.org.pkijs !== "object") + throw new Error("Name org.pkijs already exists and it's not an object" + " but " + (typeof in_window.org.pkijs)); + } + // #endregion + + // #region "org.pkijs.simpl" namespace + if(typeof in_window.org.pkijs.simpl === "undefined") + in_window.org.pkijs.simpl = {}; + else + { + if(typeof in_window.org.pkijs.simpl !== "object") + throw new Error("Name org.pkijs.simpl already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.simpl)); + } + // #endregion + + // #region "org.pkijs.simpl.cms" namespace + if(typeof in_window.org.pkijs.simpl.cms === "undefined") + in_window.org.pkijs.simpl.cms = {}; + else + { + if(typeof in_window.org.pkijs.simpl.cms !== "object") + throw new Error("Name org.pkijs.simpl.cms already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.simpl.cms)); + } + // #endregion + + // #region "org.pkijs.simpl.x509" namespace + if (typeof in_window.org.pkijs.simpl.x509 === "undefined") + in_window.org.pkijs.simpl.x509 = {}; + else + { + if (typeof in_window.org.pkijs.simpl.x509 !== "object") + throw new Error("Name org.pkijs.simpl.x509 already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.simpl.x509)); + } + // #endregion + + // #region "local" namespace + var local = {}; + // #endregion + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Functions, common for CMS module + //************************************************************************************** + in_window.org.pkijs.simpl.cms.kdfWithCounter = + function(hashFunction, Zbuffer, Counter, SharedInfo) + { + ///

ANS X9.63 Key Derivation Function having a "Counter" as a parameter + /// Used hash function + /// ArrayBuffer containing ECDH shared secret to derive from + /// Length of used kew derivation function + /// Usually DER encoded "ECC_CMS_SharedInfo" structure + + // #region Check of input parameters + switch(hashFunction.toUpperCase()) + { + case "SHA-1": + case "SHA-256": + case "SHA-384": + case "SHA-512": + break; + default: + return Promise.reject("Unknown hash function: " + hashFunction); + } + + if((Zbuffer instanceof ArrayBuffer) === false) + return Promise.reject("Please set \"Zbuffer\" as \"ArrayBuffer\""); + + if(Zbuffer.byteLength === 0) + return Promise.reject("\"Zbuffer\" has zero length, error"); + + if((SharedInfo instanceof ArrayBuffer) === false) + return Promise.reject("Please set \"SharedInfo\" as \"ArrayBuffer\""); + + if(Counter > 255) + return Promise.reject("Please set \"Counter\" variable to value less or equal to 255"); + // #endregion + + // #region Initial variables + var counterBuffer = new ArrayBuffer(4); + var counterView = new Uint8Array(counterBuffer); + counterView[0] = 0x00; + counterView[1] = 0x00; + counterView[2] = 0x00; + counterView[3] = Counter; + + var combinedBuffer = new ArrayBuffer(0); + // #endregion + + // #region Get a "crypto" extension + var crypto = in_window.org.pkijs.getCrypto(); + if(typeof crypto == "undefined") + return Promise.reject("Unable to create WebCrypto object"); + // #endregion + + // #region Create a combined ArrayBuffer for digesting + combinedBuffer = in_window.org.pkijs.concat_buffers(combinedBuffer, Zbuffer); + combinedBuffer = in_window.org.pkijs.concat_buffers(combinedBuffer, counterBuffer); + combinedBuffer = in_window.org.pkijs.concat_buffers(combinedBuffer, SharedInfo); + // #endregion + + // #region Return digest of combined ArrayBuffer and information about current counter + return crypto.digest({ + name: hashFunction + }, + combinedBuffer). + then( + function(result) + { + return { + counter: Counter, + result: result + }; + } + ); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.kdf = + function(hashFunction, Zbuffer, keydatalen, SharedInfo) + { + /// ANS X9.63 Key Derivation Function + /// Used hash function + /// ArrayBuffer containing ECDH shared secret to derive from + /// Length (!!! in BITS !!!) of used kew derivation function + /// Usually DER encoded "ECC_CMS_SharedInfo" structure + + // #region Initial variables + var hashLength = 0; + var maxCounter = 1; + + var kdfArray = new Array(); + // #endregion + + // #region Check of input parameters + switch(hashFunction.toUpperCase()) + { + case "SHA-1": + hashLength = 160; // In bits + break; + case "SHA-256": + hashLength = 256; // In bits + break; + case "SHA-384": + hashLength = 384; // In bits + break; + case "SHA-512": + hashLength = 512; // In bits + break; + default: + return Promise.reject("Unknown hash function: " + hashFunction); + } + + if((Zbuffer instanceof ArrayBuffer) === false) + return Promise.reject("Please set \"Zbuffer\" as \"ArrayBuffer\""); + + if(Zbuffer.byteLength === 0) + return Promise.reject("\"Zbuffer\" has zero length, error"); + + if((SharedInfo instanceof ArrayBuffer) === false) + return Promise.reject("Please set \"SharedInfo\" as \"ArrayBuffer\""); + // #endregion + + // #region Calculated maximum value of "Counter" variable + var quotient = keydatalen / hashLength; + + if(Math.floor(quotient) > 0) + { + maxCounter = Math.floor(quotient); + + if((quotient - maxCounter) > 0) + maxCounter++; + } + // #endregion + + // #region Create an array of "kdfWithCounter" + for(var i = 1; i <= maxCounter; i++) + kdfArray.push(in_window.org.pkijs.simpl.cms.kdfWithCounter(hashFunction, Zbuffer, i, SharedInfo)); + // #endregion + + // #region Return combined digest with specified length + return Promise.all(kdfArray). + then( + function(incomingResult) + { + // #region Initial variables + var combinedBuffer = new ArrayBuffer(0); + var currentCounter = 1; + var found = true; + // #endregion + + // #region Combine all buffer together + while(found) + { + found = false; + + for(var i = 0; i < incomingResult.length; i++) + { + if(incomingResult[i].counter === currentCounter) + { + combinedBuffer = org.pkijs.concat_buffers(combinedBuffer, incomingResult[i].result); + found = true; + break; + } + } + + currentCounter++; + } + // #endregion + + // #region Create output buffer with specified length + keydatalen >>= 3; // Divide by 8 since "keydatalen" is in bits + + if(combinedBuffer.byteLength > keydatalen) + { + var newBuffer = new ArrayBuffer(keydatalen); + var newView = new Uint8Array(newBuffer); + var combinedView = new Uint8Array(combinedBuffer); + + for(var i = 0; i < keydatalen; i++) + newView[i] = combinedView[i]; + + return newBuffer; + } + else + return combinedBuffer; // Since the situation when "combinedBuffer.byteLength < keydatalen" here we have only "combinedBuffer.byteLength === keydatalen" + // #endregion + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "CMS_CONTENT_INFO" type + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_CONTENT_INFO = + function() + { + // #region Internal properties of the object + this.contentType = ""; + this.content = new in_window.org.pkijs.asn1.ANY(); // Just to make a stub + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.CMS_CONTENT_INFO.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.contentType = arguments[0].contentType || ""; + this.content = arguments[0].content || new in_window.org.pkijs.asn1.ANY(); // Just to make a stub + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_CONTENT_INFO.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.CMS_CONTENT_INFO() + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for CMS_CONTENT_INFO"); + // #endregion + + // #region Get internal properties from parsed schema + this.contentType = asn1.result["contentType"].value_block.toString(); + this.content = asn1.result["content"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_CONTENT_INFO.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + new in_window.org.pkijs.asn1.OID({ value: this.contentType }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [this.content] // EXPLICIT ANY value + }) + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_CONTENT_INFO.prototype.toJSON = + function() + { + var _object = { + contentType: this.contentType + }; + + if(!(this.content instanceof in_window.org.pkijs.asn1.ANY)) + _object.content = this.content.toJSON(); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "OtherCertificateFormat" type + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OtherCertificateFormat = + function() + { + // #region Internal properties of the object + this.otherCertFormat = ""; + this.otherCert = new in_window.org.pkijs.asn1.ANY(); // Just to make a stub + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.OtherCertificateFormat.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.otherCertFormat = arguments[0].contentType || ""; + this.otherCert = arguments[0].content || new in_window.org.pkijs.asn1.ANY(); // Just to make a stub + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OtherCertificateFormat.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.OtherCertificateFormat() + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for OtherCertificateFormat"); + // #endregion + + // #region Get internal properties from parsed schema + this.otherCertFormat = asn1.result["otherCertFormat"].value_block.toString(); + this.otherCert = asn1.result["otherCert"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OtherCertificateFormat.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + new in_window.org.pkijs.asn1.OID({ value: this.otherCertFormat }), + this.otherCert + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OtherCertificateFormat.prototype.toJSON = + function() + { + var _object = { + otherCertFormat: this.otherCertFormat + }; + + if(!(this.otherCert instanceof in_window.org.pkijs.asn1.ANY)) + _object.otherCert = this.otherCert.toJSON(); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "OtherRevocationInfoFormat" type + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OtherRevocationInfoFormat = + function() + { + // #region Internal properties of the object + this.otherRevInfoFormat = ""; + this.otherRevInfo = new in_window.org.pkijs.asn1.ANY(); // Just to make a stub + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.OtherRevocationInfoFormat.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.otherRevInfoFormat = arguments[0].otherRevInfoFormat || ""; + this.otherRevInfo = arguments[0].otherRevInfo || new in_window.org.pkijs.asn1.ANY(); // Just to make a stub + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OtherRevocationInfoFormat.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.OtherRevocationInfoFormat() + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for OtherRevocationInfoFormat"); + // #endregion + + // #region Get internal properties from parsed schema + this.otherRevInfoFormat = asn1.result["otherRevInfoFormat"].value_block.toString(); + this.otherRevInfo = asn1.result["otherRevInfo"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OtherRevocationInfoFormat.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + new in_window.org.pkijs.asn1.OID({ value: this.otherRevInfoFormat }), + this.otherRevInfo + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OtherRevocationInfoFormat.prototype.toJSON = + function() + { + var _object = { + otherRevInfoFormat: this.otherRevInfoFormat + }; + + if(!(this.otherRevInfo instanceof in_window.org.pkijs.asn1.ANY)) + _object.otherRevInfo = this.otherRevInfo.toJSON(); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "CMS_CERTIFICATE_SET" type + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_CERTIFICATE_SET = + function() + { + // #region Internal properties of the object + this.certificates = new Array(); // Array of "CertificateChoices" + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.CMS_CERTIFICATE_SET.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.certificates = arguments[0].certificates || new Array(); // Array of "CertificateChoices" + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_CERTIFICATE_SET.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.CMS_CERTIFICATE_SET() + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for CMS_CERTIFICATE_SET"); + // #endregion + + // #region Get internal properties from parsed schema + var certificates_array = asn1.result["certificates"]; + + for(var i = 0; i < certificates_array; i++) + { + if(certificates_array[i].id_block.tag_class === 1) + this.certificates.push(new in_window.org.pkijs.simpl.CERT({ schema: certificates_array[i] })); + else + this.certificates.push(certificates_array[i]); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_CERTIFICATE_SET.prototype.toSchema = + function() + { + // #region Create array for output set + var output_array = new Array(); + + for(var i = 0; i < this.certificates.length; i++) + { + if(this.certificates[i] instanceof in_window.org.pkijs.simpl.CERT) + output_array.push(this.certificates[i].toSchema()); + else + output_array.push(this.certificates[i]); + } + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SET({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_CERTIFICATE_SET.prototype.toJSON = + function() + { + var _object = {}; + + _object.certificates = new Array(); + for(var i = 0; i < this.certificates.length; i++) + _object.certificates.push(this.certificates[i].toJSON()); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "CMS_REVOCATION_INFO_CHOICES" type + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_REVOCATION_INFO_CHOICES = + function() + { + // #region Internal properties of the object + this.crls = new Array(); // Array of "RevocationInfoChoices" + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.CMS_REVOCATION_INFO_CHOICES.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.crls = arguments[0].crls || new Array(); // Array of "RevocationInfoChoices" + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_REVOCATION_INFO_CHOICES.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.CMS_REVOCATION_INFO_CHOICES() + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for CMS_REVOCATION_INFO_CHOICES"); + // #endregion + + // #region Get internal properties from parsed schema + var crls_array = asn1.result["crls"]; + + for(var i = 0; i < crls_array; i++) + { + if(crls_array.id_block.tag_class === 1) + this.crls.push(new in_window.org.pkijs.simpl.CRL({ schema: crls_array[i] })); + else + this.crls.push(crls_array[i]); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_REVOCATION_INFO_CHOICES.prototype.toSchema = + function() + { + // #region Create array for output set + var output_array = new Array(); + + for(var i = 0; i < this.crls.length; i++) + { + if(this.crls[i] instanceof in_window.org.pkijs.simpl.CRL) + output_array.push(this.crls[i].toSchema()); + else + output_array.push(this.crls[i]); + } + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SET({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_REVOCATION_INFO_CHOICES.prototype.toJSON = + function() + { + var _object = {}; + + _object.crls = new Array(); + for(var i = 0; i < this.crls.length; i++) + _object.crls.push(this.crls[i].toJSON()); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "IssuerAndSerialNumber" type + //************************************************************************************** + in_window.org.pkijs.simpl.cms.IssuerAndSerialNumber = + function() + { + // #region Internal properties of the object + this.issuer = new in_window.org.pkijs.simpl.RDN(); + this.serialNumber = new in_window.org.pkijs.asn1.INTEGER(); // Might be a very long integer value + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.IssuerAndSerialNumber.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.issuer = arguments[0].issuer || new in_window.org.pkijs.simpl.RDN(); + this.serialNumber = arguments[0].serialNumber || new in_window.org.pkijs.asn1.INTEGER(); // Might be a very long integer value + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.IssuerAndSerialNumber.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.IssuerAndSerialNumber({ + names: { + issuer: { + names: { + block_name: "issuer" + } + }, + serialNumber: "serialNumber" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for IssuerAndSerialNumber"); + // #endregion + + // #region Get internal properties from parsed schema + this.issuer = new in_window.org.pkijs.simpl.RDN({ schema: asn1.result["issuer"] }); + this.serialNumber = asn1.result["serialNumber"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.IssuerAndSerialNumber.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + this.issuer.toSchema(), + this.serialNumber + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.IssuerAndSerialNumber.prototype.toJSON = + function() + { + return { + issuer: this.issuer.toJSON(), + serialNumber: this.serialNumber.toJSON() + }; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "Attribute" type + //************************************************************************************** + in_window.org.pkijs.simpl.cms.Attribute = + function() + { + // #region Internal properties of the object + this.attrType = ""; + this.attrValues = new Array(); // Array of any attribute values + + // OPTIONAL this.parsedValue - Parsed "attrValues" in case of well-known "attrType" + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.Attribute.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.attrType = arguments[0].attrType || ""; + this.attrValues = arguments[0].attrValues || new Array(); // Array of any attribute values + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.Attribute.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.Attribute({ + names: { + attrType: "attrType", + attrValues: "attrValues" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for Attribute"); + // #endregion + + // #region Get internal properties from parsed schema + this.attrType = asn1.result["attrType"].value_block.toString(); + this.attrValues = asn1.result["attrValues"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.Attribute.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + new in_window.org.pkijs.asn1.OID({ value: this.attrType }), + new in_window.org.pkijs.asn1.SET({ + value: this.attrValues + }) + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.Attribute.prototype.toJSON = + function() + { + var _object = { + attrType: this.attrType + }; + + _object.attrValues = new Array(); + for(var i = 0; i < this.attrValues.length; i++) + _object.attrValues.push(this.attrValues[i].toJSON()); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "RSAES_OAEP_params" type (RFC3447) + //************************************************************************************** + in_window.org.pkijs.simpl.cms.RSAES_OAEP_params = + function() + { + // #region Internal properties of the object + // OPTIONAL this.hashAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + // OPTIONAL this.maskGenAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + // OPTIONAL this.pSourceAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.RSAES_OAEP_params.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + if("hashAlgorithm" in arguments[0]) + this.hashAlgorithm = arguments[0].hashAlgorithm; + + if("maskGenAlgorithm" in arguments[0]) + this.maskGenAlgorithm = arguments[0].maskGenAlgorithm; + + if("pSourceAlgorithm" in arguments[0]) + this.pSourceAlgorithm = arguments[0].pSourceAlgorithm; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.RSAES_OAEP_params.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.RSAES_OAEP_params({ + names: { + hashAlgorithm: { + names: { + block_name: "hashAlgorithm" + } + }, + maskGenAlgorithm: { + names: { + block_name: "maskGenAlgorithm" + } + }, + pSourceAlgorithm: { + names: { + block_name: "pSourceAlgorithm" + } + } + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for RSAES_OAEP_params"); + // #endregion + + // #region Get internal properties from parsed schema + if("hashAlgorithm" in asn1.result) + this.hashAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["hashAlgorithm"] }); + + if("maskGenAlgorithm" in asn1.result) + this.maskGenAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["maskGenAlgorithm"] }); + + if("pSourceAlgorithm" in asn1.result) + this.pSourceAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["pSourceAlgorithm"] }); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.RSAES_OAEP_params.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + if("hashAlgorithm" in this) + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [this.hashAlgorithm.toSchema()] + })); + + if("maskGenAlgorithm" in this) + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [this.maskGenAlgorithm.toSchema()] + })); + + if("pSourceAlgorithm" in this) + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 2 // [2] + }, + value: [this.pSourceAlgorithm.toSchema()] + })); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.RSAES_OAEP_params.prototype.toJSON = + function() + { + var _object = {}; + + if("hashAlgorithm" in this) + _object.hashAlgorithm = this.hashAlgorithm.toJSON(); + + if("maskGenAlgorithm" in this) + _object.maskGenAlgorithm = this.maskGenAlgorithm.toJSON(); + + if("pSourceAlgorithm" in this) + _object.pSourceAlgorithm = this.pSourceAlgorithm.toJSON(); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "PBKDF2_params" type (RFC2898) + //************************************************************************************** + in_window.org.pkijs.simpl.cms.PBKDF2_params = + function() + { + // #region Internal properties of the object + this.salt = new in_window.org.pkijs.emptyObject(); + this.iterationCount = 0; + // OPTIONAL this.keyLength = 0; + // OPTIONAL this.prf = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.PBKDF2_params.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.salt = arguments[0].salt || new in_window.org.pkijs.emptyObject(); + this.iterationCount = arguments[0].iterationCount || 0; + + if("keyLength" in arguments[0]) + this.keyLength = arguments[0].keyLength; + + if("prf" in arguments[0]) + this.prf = arguments[0].prf; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.PBKDF2_params.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.PBKDF2_params({ + names: { + salt_primitive: "salt", + salt_constructed: { + names: { + block_name: "salt" + } + }, + iterationCount: "iterationCount", + keyLength: "keyLength", + prf: { + names: { + block_name: "prf", + optional: true + } + } + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for PBKDF2_params"); + // #endregion + + // #region Get internal properties from parsed schema + this.salt = asn1.result["salt"]; + this.iterationCount = asn1.result["iterationCount"].value_block.value_dec; + + if("keyLength" in asn1.result) + this.keyLength = asn1.result["keyLength"].value_block.value_dec; + + if("prf" in asn1.result) + this.prf = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["prf"] }); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.PBKDF2_params.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + output_array.push(this.salt); + output_array.push(new in_window.org.pkijs.asn1.INTEGER({ value: this.iterationCount })); + + if("keyLength" in this) + output_array.push(new in_window.org.pkijs.asn1.INTEGER({ value: this.keyLength })); + + if("prf" in this) + output_array.push(this.prf.toSchema()); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.PBKDF2_params.prototype.toJSON = + function() + { + var _object = { + salt: this.salt.toJSON(), + iterationCount: this.iterationCount + }; + + if("keyLength" in this) + _object.keyLength = this.keyLength; + + if("prf" in this) + _object.prf = this.prf.toJSON(); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "PBES2_params" type (RFC2898) + //************************************************************************************** + in_window.org.pkijs.simpl.cms.PBES2_params = + function() + { + // #region Internal properties of the object + this.keyDerivationFunc = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.encryptionScheme = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.PBES2_params.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.keyDerivationFunc = arguments[0].keyDerivationFunc || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.encryptionScheme = arguments[0].encryptionScheme || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.PBES2_params.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.PBES2_params({ + names: { + keyDerivationFunc: { + names: { + block_name: "keyDerivationFunc" + } + }, + encryptionScheme: { + names: { + block_name: "encryptionScheme" + } + } + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for PBES2_params"); + // #endregion + + // #region Get internal properties from parsed schema + this.keyDerivationFunc = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["keyDerivationFunc"] }); + this.encryptionScheme = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["encryptionScheme"] }); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.PBES2_params.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + this.keyDerivationFunc.toSchema(), + this.encryptionScheme.toSchema() + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.PBES2_params.prototype.toJSON = + function() + { + return { + keyDerivationFunc: this.keyDerivationFunc.toJSON(), + encryptionScheme: this.encryptionScheme.toJSON() + }; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "SignedUnsignedAttributes" type + //************************************************************************************** + in_window.org.pkijs.simpl.cms.SignedUnsignedAttributes = + function() + { + // #region Internal properties of the object + this.type = 0; // "SignedAttributes" = 0, "UnsignedAttributes" = 1 + this.attributes = new Array(); // Array of Attribute objects + this.encoded_value = new ArrayBuffer(0); // Need to have it in order to successfully process with signature verification + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.SignedUnsignedAttributes.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.type = arguments[0].type || 0; // "SignedAttributes" = 0, "UnsignedAttributes" = 1 + this.attributes = arguments[0].attributes || new Array(); // Array of Attribute objects + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.SignedUnsignedAttributes.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.SignedUnsignedAttributes({ + names: { + attributes: "attributes" + } + }, this.type) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for SignedUnsignedAttributes"); + // #endregion + + // #region Get internal properties from parsed schema + this.type = asn1.result.id_block.tag_number; + this.encoded_value = asn1.result.value_before_decode; + + // #region Change type from "[0]" to "SET" accordingly to standard + var encoded_view = new Uint8Array(this.encoded_value); + encoded_view[0] = 0x31; + // #endregion + + if(("attributes" in asn1.result) === false) + { + if(this.type === 0) + throw new Error("Wrong structure of SignedUnsignedAttributes"); + else + return; // Not so important in case of "UnsignedAttributes" + } + + var attributes_array = asn1.result["attributes"]; + + for(var i = 0; i < attributes_array.length; i++) + this.attributes.push(new in_window.org.pkijs.simpl.cms.Attribute({ schema: attributes_array[i] })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.SignedUnsignedAttributes.prototype.toSchema = + function() + { + // #region Create array of attributes + var attributes_array = new Array(); + + for(var i = 0; i < this.attributes.length; i++) + attributes_array.push(this.attributes[i].toSchema()); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: this.type // "SignedAttributes" = 0, "UnsignedAttributes" = 1 + }, + value: attributes_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.SignedUnsignedAttributes.prototype.toJSON = + function() + { + var _object = { + type: this.type + }; + + _object.attributes = new Array(); + for(var i = 0; i < this.attributes.length; i++) + _object.attributes.push(this.attributes[i].toJSON()); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "CMS_SIGNER_INFO" type + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_SIGNER_INFO = + function() + { + // #region Internal properties of the object + this.version = 0; + this.sid = new in_window.org.pkijs.asn1.ANY(); // Just for making stub + this.digestAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + // OPTIONAL this.signedAttrs = new in_window.org.pkijs.simpl.cms.SignedUnsignedAttributes(); + this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.signature = new in_window.org.pkijs.asn1.OCTETSTRING(); + // OPTIONAL this.unsignedAttrs = new in_window.org.pkijs.simpl.cms.SignedUnsignedAttributes(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.CMS_SIGNER_INFO.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.version = arguments[0].version || 0; + this.sid = arguments[0].sid || new in_window.org.pkijs.asn1.ANY(); // Just for making stub + this.digestAlgorithm = arguments[0].digestAlgorithm || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + if("signedAttrs" in arguments[0]) + this.signedAttrs = arguments[0].signedAttrs; + this.signatureAlgorithm = arguments[0].signatureAlgorithm || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.signature = arguments[0].signature || new in_window.org.pkijs.asn1.OCTETSTRING(); + if("unsignedAttrs" in arguments[0]) + this.unsignedAttrs = arguments[0].unsignedAttrs; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_SIGNER_INFO.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.CMS_SIGNER_INFO() + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for CMS_SIGNER_INFO"); + // #endregion + + // #region Get internal properties from parsed schema + this.version = asn1.result["SignerInfo.version"].value_block.value_dec; + + var current_sid = asn1.result["SignerInfo.sid"]; + if(current_sid.id_block.tag_class === 1) + this.sid = new in_window.org.pkijs.simpl.cms.IssuerAndSerialNumber({ schema: current_sid }); + else + this.sid = current_sid; + + this.digestAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["SignerInfo.digestAlgorithm"] }); + if("SignerInfo.signedAttrs" in asn1.result) + this.signedAttrs = new in_window.org.pkijs.simpl.cms.SignedUnsignedAttributes({ schema: asn1.result["SignerInfo.signedAttrs"] }); + this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["SignerInfo.signatureAlgorithm"] }); + this.signature = asn1.result["SignerInfo.signature"]; + if("SignerInfo.unsignedAttrs" in asn1.result) + { + this.unsignedAttrs = new in_window.org.pkijs.simpl.cms.SignedUnsignedAttributes(); + this.unsignedAttrs.type = 1; // Unsigned attributes + this.unsignedAttrs.fromSchema(asn1.result["SignerInfo.unsignedAttrs"]); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_SIGNER_INFO.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + output_array.push(new in_window.org.pkijs.asn1.INTEGER({ value: this.version })); + + if(this.sid instanceof in_window.org.pkijs.simpl.cms.IssuerAndSerialNumber) + output_array.push(this.sid.toSchema()); + else + output_array.push(this.sid); + + output_array.push(this.digestAlgorithm.toSchema()); + if("signedAttrs" in this) + output_array.push(this.signedAttrs.toSchema()); + output_array.push(this.signatureAlgorithm.toSchema()); + output_array.push(this.signature); + if("unsignedAttrs" in this) + output_array.push(this.unsignedAttrs.toSchema()); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_SIGNER_INFO.prototype.toJSON = + function() + { + var _object = { + version: this.version + }; + + if(!(this.sid instanceof in_window.org.pkijs.asn1.ANY)) + _object.sid = this.sid.toJSON(); + + _object.digestAlgorithm = this.digestAlgorithm.toJSON(); + + if("signedAttrs" in this) + _object.signedAttrs = this.signedAttrs.toJSON(); + + _object.signatureAlgorithm = this.signatureAlgorithm.toJSON(); + _object.signature = this.signature.toJSON(); + + if("unsignedAttrs" in this) + _object.unsignedAttrs = this.unsignedAttrs.toJSON(); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "EncapsulatedContentInfo" type + //************************************************************************************** + in_window.org.pkijs.simpl.cms.EncapsulatedContentInfo = + function() + { + // #region Internal properties of the object + this.eContentType = ""; + // OPTIONAL this.eContent = new in_window.org.pkijs.asn1.OCTETSTRING(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.EncapsulatedContentInfo.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.eContentType = arguments[0].eContentType || ""; + if("eContent" in arguments[0]) + { + this.eContent = arguments[0].eContent; + + if((this.eContent.id_block.tag_class === 1) && + (this.eContent.id_block.tag_number === 4)) + { + // #region Divide OCTETSTRING value down to small pieces + if(this.eContent.id_block.is_constructed === false) + { + var constr_string = new in_window.org.pkijs.asn1.OCTETSTRING({ + id_block: { is_constructed: true }, + is_constructed: true + }); + + var offset = 0; + var length = this.eContent.value_block.value_hex.byteLength; + + while(length > 0) + { + var piece_view = new Uint8Array(this.eContent.value_block.value_hex, offset, ((offset + 65536) > this.eContent.value_block.value_hex.byteLength) ? (this.eContent.value_block.value_hex.byteLength - offset) : 65536); + var _array = new ArrayBuffer(piece_view.length); + var _view = new Uint8Array(_array); + + for(var i = 0; i < _view.length; i++) + _view[i] = piece_view[i]; + + constr_string.value_block.value.push(new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: _array })); + + length -= piece_view.length; + offset += piece_view.length; + } + + this.eContent = constr_string; + } + // #endregion + } + } + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.EncapsulatedContentInfo.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.EncapsulatedContentInfo({ + names: { + eContentType: "eContentType", + eContent: "eContent" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for EncapsulatedContentInfo"); + // #endregion + + // #region Get internal properties from parsed schema + this.eContentType = asn1.result["eContentType"].value_block.toString(); + if("eContent" in asn1.result) + this.eContent = asn1.result["eContent"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.EncapsulatedContentInfo.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + output_array.push(new in_window.org.pkijs.asn1.OID({ value: this.eContentType })); + if("eContent" in this) + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [this.eContent] + })); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.EncapsulatedContentInfo.prototype.toJSON = + function() + { + var _object = { + eContentType: this.eContentType + }; + + if("eContent" in this) + _object.eContent = this.eContent.toJSON(); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "CMS_SIGNED_DATA" type + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_SIGNED_DATA = + function() + { + // #region Internal properties of the object + this.version = 0; + this.digestAlgorithms = new Array(); // Array of AlgorithmIdentifier + this.encapContentInfo = new in_window.org.pkijs.simpl.cms.EncapsulatedContentInfo(); + //this.certificates - OPTIONAL + //this.crls - OPTIONAL + this.signerInfos = new Array(); // Array of CMS_SIGNER_INFO + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.CMS_SIGNED_DATA.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.version = arguments[0].version || 0; + this.digestAlgorithms = arguments[0].digestAlgorithms || new Array(); // Array of AlgorithmIdentifier + this.encapContentInfo = arguments[0].encapContentInfo || new in_window.org.pkijs.simpl.cms.EncapsulatedContentInfo(); + if("certificates" in arguments[0]) + this.certificates = arguments[0].certificates; + if("crls" in arguments[0]) + this.crls = arguments[0].crls; + this.signerInfos = arguments[0].signerInfos || new Array(); // Array of CMS_SIGNER_INFO + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_SIGNED_DATA.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.CMS_SIGNED_DATA() + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for CMS_SIGNED_DATA"); + // #endregion + + // #region Get internal properties from parsed schema + this.version = asn1.result["SignedData.version"].value_block.value_dec; + + var algorithms_array = asn1.result["SignedData.digestAlgorithms"]; + for(var i = 0; i < algorithms_array.length; i++) + this.digestAlgorithms.push(new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: algorithms_array[i] })); + + this.encapContentInfo = new in_window.org.pkijs.simpl.cms.EncapsulatedContentInfo({ schema: asn1.result["SignedData.encapContentInfo"] }); + + if("SignedData.certificates" in asn1.result) + { + this.certificates = new Array(); + + var current_certificates = asn1.result["SignedData.certificates"]; + for(var k = 0; k < current_certificates.length; k++) + { + if(current_certificates[k].id_block.tag_class === 1) + this.certificates.push(new in_window.org.pkijs.simpl.CERT({ schema: current_certificates[k] })); + else + { + if((current_certificates[k].id_block.tag_class == 3) && (current_certificates[k].id_block.tag_number == 3)) + { + // #region Create SEQUENCE from [3] + current_certificates[k].id_block.tag_class = 1; // UNIVERSAL + current_certificates[k].id_block.tag_number = 16; // SEQUENCE + // #endregion + + this.certificates.push(new in_window.org.pkijs.simpl.cms.OtherCertificateFormat({ schema: current_certificates[k] })); + } + //else // For now we would ignore "AttributeCertificateV1" and "AttributeCertificateV1" + } + } + } + + if("SignedData.crls" in asn1.result) + { + this.crls = new Array(); + + var current_crls = asn1.result["SignedData.crls"]; + for(var l = 0; l < current_crls.length; l++) + { + if(current_crls[l].id_block.tag_class === 1) + this.crls.push(new in_window.org.pkijs.simpl.CRL({ schema: current_crls[l] })); + else + { + // #region Create SEQUENCE from [1] + current_crls[l].id_block.tag_class = 1; // UNIVERSAL + current_crls[l].id_block.tag_number = 16; // SEQUENCE + // #endregion + + this.crls.push(new in_window.org.pkijs.simpl.cms.OtherRevocationInfoFormat({ schema: current_crls[l] })); + } + } + } + + var signer_infos = asn1.result["SignedData.signerInfos"]; + for(var j = 0; j < signer_infos.length; j++) + this.signerInfos.push(new in_window.org.pkijs.simpl.CMS_SIGNER_INFO({ schema: signer_infos[j] })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_SIGNED_DATA.prototype.toSchema = + function(encodeFlag) + { + /// If param equal to false then create TBS schema via decoding stored value. In othe case create TBS schema via assembling from TBS parts. + + if(typeof encodeFlag === "undefined") + encodeFlag = false; + + // #region Create array for output sequence + var output_array = new Array(); + + output_array.push(new in_window.org.pkijs.asn1.INTEGER({ value: this.version })); + + // #region Create array of digest algorithms + var digest_algorithms = new Array(); + for(var i = 0; i < this.digestAlgorithms.length; i++) + digest_algorithms.push(this.digestAlgorithms[i].toSchema(encodeFlag)); + + output_array.push(new in_window.org.pkijs.asn1.SET({ + value: digest_algorithms + })); + // #endregion + + output_array.push(this.encapContentInfo.toSchema()); + + if("certificates" in this) + { + var current_certificates = new Array(); + + for(var j = 0; j < this.certificates.length; j++) + { + if(this.certificates[j] instanceof in_window.org.pkijs.simpl.cms.OtherCertificateFormat) + { + var certificateSchema = this.certificates[j].toSchema(encodeFlag); + + certificateSchema.id_block.tag_class = 3; + certificateSchema.id_block.tag_number = 3; + + current_certificates.push(certificateSchema); + } + else + current_certificates.push(this.certificates[j].toSchema(encodeFlag)); + } + + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: current_certificates + })); + } + + if("crls" in this) + { + var current_crls = new Array(); + + for(var k = 0; k < this.crls.length; k++) + { + if(this.crls[k] instanceof in_window.org.pkijs.simpl.cms.OtherRevocationInfoFormat) + { + var crlSchema = this.crls[k].toSchema(encodeFlag); + + crlSchema.id_block.tag_class = 3; + crlSchema.id_block.tag_number = 1; + + current_crls.push(crlSchema); + } + else + current_crls.push(this.crls[k].toSchema(encodeFlag)); + } + + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: current_crls + })); + } + + // #region Create array of signer infos + var signer_infos = new Array(); + + for(var l = 0; l < this.signerInfos.length; l++) + signer_infos.push(this.signerInfos[l].toSchema(encodeFlag)); + + output_array.push(new in_window.org.pkijs.asn1.SET({ + value: signer_infos + })); + // #endregion + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_SIGNED_DATA.prototype.verify = + function() + { + // #region Global variables + var sequence = Promise.resolve(); + + var certificates = this.certificates; + var signerInfos = this.signerInfos; + var encapContentInfo = this.encapContentInfo; + + var data = new ArrayBuffer(0); + var messageDigestValue = new ArrayBuffer(0); + + var publicKey; + var algorithm; + + var sha_algorithm = ""; + + var signerIndex = -1; + var cert_index = -1; + var signer_cert = {}; + + var trusted_certs = new Array(); + + var checkDate = new Date(); + + var checkChain = true; + var includeSignerCertificate = false; + + var _this = this; + + var extendedMode = false; + // #endregion + + // #region Get a "crypto" extension + var crypto = in_window.org.pkijs.getCrypto(); + if(typeof crypto == "undefined") + return Promise.reject("Unable to create WebCrypto object"); + // #endregion + + // #region Get a signer number + if(arguments[0] instanceof Object) + { + if("signer" in arguments[0]) + signerIndex = arguments[0].signer; + + if("data" in arguments[0]) // Detached data + data = arguments[0].data; + + if("trusted_certs" in arguments[0]) + trusted_certs = arguments[0].trusted_certs; + + if("checkDate" in arguments[0]) + checkDate = arguments[0].checkDate; + + if("checkChain" in arguments[0]) + checkChain = arguments[0].checkChain; + + if("includeSignerCertificate" in arguments[0]) + includeSignerCertificate = arguments[0].includeSignerCertificate; + + if("extendedMode" in arguments[0]) + extendedMode = arguments[0].extendedMode; + } + + if(signerIndex === (-1)) + { + if(extendedMode) + { + return Promise.reject({ + date: checkDate, + code: 1, + message: "Unable to get signer index from input parameters", + signatureVerified: null, + signerCertificate: null, + signerCertificateVerified: null + }); + } + + return Promise.reject("Unable to get signer index from input parameters"); + } + // #endregion + + // #region Check that certificates field was included in signed data + if(("certificates" in this) === false) + { + if(extendedMode) + { + return Promise.reject({ + date: checkDate, + code: 2, + message: "No certificates attached to this signed data", + signatureVerified: null, + signerCertificate: null, + signerCertificateVerified: null + }); + } + + return Promise.reject("No certificates attached to this signed data"); + } + // #endregion + + // #region Find a certificate for specified signer + if(this.signerInfos[signerIndex].sid instanceof in_window.org.pkijs.simpl.cms.IssuerAndSerialNumber) + { + sequence = sequence.then( + function() + { + for(var i = 0; certificates.length; i++) + { + if((certificates[i] instanceof in_window.org.pkijs.simpl.CERT) == false) + continue; + + if((certificates[i].issuer.isEqual(signerInfos[signerIndex].sid.issuer)) && + (certificates[i].serialNumber.isEqual(signerInfos[signerIndex].sid.serialNumber))) + { + signer_cert = certificates[i]; + return Promise.resolve(); + } + } + + if(extendedMode) + { + return Promise.reject({ + date: checkDate, + code: 3, + message: "Unable to find signer certificate", + signatureVerified: null, + signerCertificate: null, + signerCertificateVerified: null + }); + } + + return Promise.reject("Unable to find signer certificate"); + } + ); + } + else // Find by SubjectKeyIdentifier + { + sequence = sequence.then( + function() + { + var digest_promises = new Array(); + + for(var i = 0; i < certificates.length; i++) + { + if((certificates[i] instanceof in_window.org.pkijs.simpl.CERT) == false) + continue; + + digest_promises.push(crypto.digest({ name: "sha-1" }, new Uint8Array(certificates[i].subjectPublicKeyInfo.subjectPublicKey.value_block.value_hex))); + } + + return Promise.all(digest_promises).then( + function(results) + { + for(var i = 0; i < certificates.length; i++) + { + if((certificates[i] instanceof in_window.org.pkijs.simpl.CERT) == false) + continue; + + if(in_window.org.pkijs.isEqual_buffer(results[i], signerInfos[signerIndex].sid.value_block.value_hex)) + { + signer_cert = certificates[i]; + return Promise.resolve(); + } + } + + if(extendedMode) + { + return Promise.reject({ + date: checkDate, + code: 3, + message: "Unable to find signer certificate", + signatureVerified: null, + signerCertificate: null, + signerCertificateVerified: null + }); + } + + return Promise.reject("Unable to find signer certificate"); + }, + function(error) + { + if(extendedMode) + { + return Promise.reject({ + date: checkDate, + code: 3, + message: "Unable to find signer certificate", + signatureVerified: null, + signerCertificate: null, + signerCertificateVerified: null + }); + } + + return Promise.reject("Unable to find signer certificate"); + } + ); + } + ); + } + // #endregion + + // #region Verify internal digest in case of "tSTInfo" content type + sequence = sequence.then( + function() + { + if(encapContentInfo.eContentType == "1.2.840.113549.1.9.16.1.4") + { + // #region Check "eContent" precense + if(("eContent" in encapContentInfo) == false) + return false; + // #endregion + + // #region Initialize TST_INFO value + var asn1 = in_window.org.pkijs.fromBER(encapContentInfo.eContent.value_block.value_hex); + var tstInfo; + + try + { + tstInfo = new in_window.org.pkijs.simpl.TST_INFO({ schema: asn1.result }); + } + catch(ex) + { + return false; + } + // #endregion + + // #region Check that we do have detached data content + if(data.byteLength === 0) + { + if(extendedMode) + { + return Promise.reject({ + date: checkDate, + code: 4, + message: "Missed detached data input array", + signatureVerified: null, + signerCertificate: signer_cert, + signerCertificateVerified: null + }); + } + + return Promise.reject("Missed detached data input array"); + } + // #endregion + + return tstInfo.verify({ data: data }); + } + else + { + return true; + } + } + ); + // #endregion + + // #region Make additional verification for signer's certificate + function checkCA(cert) + { + /// Certificate to find CA flag for + + // #region Do not include signer's certificate + if((cert.issuer.isEqual(signer_cert.issuer) === true) && (cert.serialNumber.isEqual(signer_cert.serialNumber) === true)) + return null; + // #endregion + + var isCA = false; + + for(var i = 0; i < cert.extensions.length; i++) + { + if(cert.extensions[i].extnID === "2.5.29.19") // BasicConstraints + { + if("cA" in cert.extensions[i].parsedValue) + { + if(cert.extensions[i].parsedValue.cA === true) + isCA = true; + } + } + } + + if(isCA) + return cert; + else + return null; + } + + if(checkChain) + { + sequence = sequence.then( + function(result) + { + // #region Veify result of previous operation + if(result == false) + return false; + // #endregion + + var checkCA_promises = new Array(); + + for(var i = 0; i < _this.certificates.length; i++) + { + if((_this.certificates[i] instanceof in_window.org.pkijs.simpl.CERT) == false) + continue; + + checkCA_promises.push(checkCA(_this.certificates[i])); + } + + return Promise.all(checkCA_promises).then( + function(promiseResults) + { + var additional_certs = new Array(); + + for(var i = 0; i < promiseResults.length; i++) + { + if(promiseResults[i] !== null) + additional_certs.push(promiseResults[i]); + } + + additional_certs.push(signer_cert); + + var cert_chain_simpl = new in_window.org.pkijs.simpl.CERT_CHAIN({ + checkDate: checkDate, + certs: additional_certs, + trusted_certs: trusted_certs + }); + if("crls" in _this) + { + for(var i = 0; i < _this.crls.length; i++) + { + if(_this.crls[i] instanceof in_window.org.pkijs.simpl.CRL) + cert_chain_simpl.crls.push(_this.crls[i]); + else // Assumed "revocation value" has "OtherRevocationInfoFormat" + { + if(_this.crls[i].otherRevInfoFormat == "1.3.6.1.5.5.7.48.1.1") // Basic OCSP response + cert_chain_simpl.ocsps.push(new in_window.org.pkijs.simpl.OCSP_BASIC_RESPONSE({ schema: _this.crls[i].otherRevInfo })); + } + } + } + if("ocsps" in _this) + { + for(var i = 0; i < _this.ocsps.length; i++) + { + cert_chain_simpl.ocsps.push(_this.ocsps[i]); + } + } + + return cert_chain_simpl.verify().then( + function(result) + { + if(result.result === true) + return Promise.resolve(true); + else + { + if(extendedMode) + { + return Promise.reject({ + date: checkDate, + code: 5, + message: "Validation of signer's certificate failed", + signatureVerified: null, + signerCertificate: signer_cert, + signerCertificateVerified: false + }); + } + + return Promise.reject("Validation of signer's certificate failed"); + } + }, + function(error) + { + if(extendedMode) + { + return Promise.reject({ + date: checkDate, + code: 5, + message: "Validation of signer's certificate failed with error: " + ((error instanceof Object) ? error.result_message : error), + signatureVerified: null, + signerCertificate: signer_cert, + signerCertificateVerified: false + }); + } + + return Promise.reject("Validation of signer's certificate failed with error: " + ((error instanceof Object) ? error.result_message : error)); + } + ); + }, + function(promiseError) + { + if(extendedMode) + { + return Promise.reject({ + date: checkDate, + code: 6, + message: "Error during checking certificates for CA flag: " + promiseError, + signatureVerified: null, + signerCertificate: signer_cert, + signerCertificateVerified: null + }); + } + + return Promise.reject("Error during checking certificates for CA flag: " + promiseError); + } + ); + } + ); + } + // #endregion + + // #region Find signer's hashing algorithm + sequence = sequence.then( + function(result) + { + // #region Veify result of previous operation + if(result == false) + return false; + // #endregion + + var shaAlgorithm = in_window.org.pkijs.getAlgorithmByOID(signerInfos[signerIndex].digestAlgorithm.algorithm_id); + if(("name" in shaAlgorithm) === false) + { + if(extendedMode) + { + return Promise.reject({ + date: checkDate, + code: 7, + message: "Unsupported signature algorithm: " + _this.signerInfos[signerIndex].digestAlgorithm.algorithm_id, + signatureVerified: null, + signerCertificate: signer_cert, + signerCertificateVerified: true + }); + } + + return Promise.reject("Unsupported signature algorithm: " + _this.signerInfos[signerIndex].digestAlgorithm.algorithm_id); + } + + sha_algorithm = shaAlgorithm.name; + + return true; + } + ); + // #endregion + + // #region Create correct data block for verification + sequence = sequence.then( + function(result) + { + // #region Veify result of previous operation + if(result == false) + return false; + // #endregion + + if("eContent" in encapContentInfo) // Attached data + { + if((encapContentInfo.eContent.id_block.tag_class === 1) && + (encapContentInfo.eContent.id_block.tag_number === 4)) + { + if(encapContentInfo.eContent.id_block.is_constructed === false) + data = encapContentInfo.eContent.value_block.value_hex; + else + { + for(var i = 0; i < encapContentInfo.eContent.value_block.value.length; i++) + data = in_window.org.pkijs.concat_buffers(data, encapContentInfo.eContent.value_block.value[i].value_block.value_hex); + } + } + else + data = encapContentInfo.eContent.value_block.value_hex; + } + else // Detached data + { + if(data.byteLength === 0) // Check that "data" already provided by function parameter + { + if(extendedMode) + { + return Promise.reject({ + date: checkDate, + code: 8, + message: "Missed detached data input array", + signatureVerified: null, + signerCertificate: signer_cert, + signerCertificateVerified: true + }); + } + + return Promise.reject("Missed detached data input array"); + } + } + + if("signedAttrs" in signerInfos[signerIndex]) + { + // #region Check mandatory attributes + var foundContentType = false; + var foundMessageDigest = false; + + for(var i = 0; i < signerInfos[signerIndex].signedAttrs.attributes.length; i++) + { + // #region Check that "content-type" attribute exists + if(signerInfos[signerIndex].signedAttrs.attributes[i].attrType == "1.2.840.113549.1.9.3") + foundContentType = true; + // #endregion + + // #region Check that "message-digest" attribute exists + if(signerInfos[signerIndex].signedAttrs.attributes[i].attrType == "1.2.840.113549.1.9.4") + { + foundMessageDigest = true; + messageDigestValue = signerInfos[signerIndex].signedAttrs.attributes[i].attrValues[0].value_block.value_hex; + } + // #endregion + + // #region Speed-up searching + if(foundContentType && foundMessageDigest) + break; + // #endregion + } + + if(foundContentType == false) + { + if(extendedMode) + { + return Promise.reject({ + date: checkDate, + code: 9, + message: "Attribute \"content-type\" is a mandatory attribute for \"signed attributes\"", + signatureVerified: null, + signerCertificate: signer_cert, + signerCertificateVerified: true + }); + } + + return Promise.reject("Attribute \"content-type\" is a mandatory attribute for \"signed attributes\""); + } + + if(foundMessageDigest == false) + { + if(extendedMode) + { + return Promise.reject({ + date: checkDate, + code: 10, + message: "Attribute \"message-digest\" is a mandatory attribute for \"signed attributes\"", + signatureVerified: null, + signerCertificate: signer_cert, + signerCertificateVerified: true + }); + } + + return Promise.reject("Attribute \"message-digest\" is a mandatory attribute for \"signed attributes\""); + } + // #endregion + } + + return true; + } + ); + // #endregion + + // #region Import public key from signer's certificate + sequence = sequence.then( + function(result) + { + // #region Veify result of previous operation + if(result == false) + return false; + // #endregion + + // #region Get information about public key algorithm and default parameters for import + var algorithmObject = in_window.org.pkijs.getAlgorithmByOID(signer_cert.signatureAlgorithm.algorithm_id); + if(("name" in algorithmObject) === false) + { + if(extendedMode) + { + return Promise.reject({ + date: checkDate, + code: 11, + message: "Unsupported public key algorithm: " + signer_cert.signatureAlgorithm.algorithm_id, + signatureVerified: null, + signerCertificate: signer_cert, + signerCertificateVerified: true + }); + } + + return Promise.reject("Unsupported public key algorithm: " + signer_cert.signatureAlgorithm.algorithm_id); + } + + var algorithm_name = algorithmObject.name; + + var algorithm = in_window.org.pkijs.getAlgorithmParameters(algorithm_name, "importkey"); + if("hash" in algorithm.algorithm) + algorithm.algorithm.hash.name = sha_algorithm; + + // #region Special case for ECDSA + if(algorithm_name === "ECDSA") + { + // #region Get information about named curve + if((signer_cert.subjectPublicKeyInfo.algorithm.algorithm_params instanceof in_window.org.pkijs.asn1.OID) === false) + return Promise.reject("Incorrect type for ECDSA public key parameters"); + + var curveObject = in_window.org.pkijs.getAlgorithmByOID(signer_cert.subjectPublicKeyInfo.algorithm.algorithm_params.value_block.toString()); + if(("name" in curveObject) === false) + return Promise.reject("Unsupported named curve algorithm: " + signer_cert.subjectPublicKeyInfo.algorithm.algorithm_params.value_block.toString()); + // #endregion + + algorithm.algorithm.namedCurve = curveObject.name; + } + // #endregion + // #endregion + + var publicKeyInfo_schema = signer_cert.subjectPublicKeyInfo.toSchema(); + var publicKeyInfo_buffer = publicKeyInfo_schema.toBER(false); + var publicKeyInfo_view = new Uint8Array(publicKeyInfo_buffer); + + return crypto.importKey("spki", publicKeyInfo_view, algorithm.algorithm, true, algorithm.usages); + } + ); + // #endregion + + // #region Verify signer's signature + sequence = sequence.then( + function(result) + { + // #region Veify result of previous operation + if(typeof result == "boolean") + return false; + // #endregion + + publicKey = result; + + // #region Verify "message-digest" attribute in case of "signedAttrs" + if("signedAttrs" in signerInfos[signerIndex]) + { + return crypto.digest(sha_algorithm, new Uint8Array(data)); + } + else + return true; + // #endregion + } + ).then( + function(result) + { + if("signedAttrs" in signerInfos[signerIndex]) + { + if(in_window.org.pkijs.isEqual_buffer(result, messageDigestValue)) + { + data = signerInfos[signerIndex].signedAttrs.encoded_value; + return true; + } + else + { + return false; + } + } + else + { + return true; + } + } + ).then( + function(result) + { + // #region Check result of previous operation + if(result == false) + return false; + // #endregion + + // #region Get default algorithm parameters for verification + algorithm = in_window.org.pkijs.getAlgorithmParameters(publicKey.algorithm.name, "verify"); + if("hash" in algorithm.algorithm) + algorithm.algorithm.hash.name = sha_algorithm; + // #endregion + + // #region Special case for RSA-PSS + if(publicKey.algorithm.name === "RSA-PSS") + { + var pssParameters; + + try + { + pssParameters = new in_window.org.pkijs.simpl.x509.RSASSA_PSS_params({ schema: signerInfos[signerIndex].signatureAlgorithm.algorithm_params }); + } + catch(ex) + { + if(extendedMode) + { + return Promise.reject({ + date: checkDate, + code: 12, + message: ex, + signatureVerified: null, + signerCertificate: signer_cert, + signerCertificateVerified: true + }); + } + + return Promise.reject(ex); + } + + if("saltLength" in pssParameters) + algorithm.algorithm.saltLength = pssParameters.saltLength; + else + algorithm.algorithm.saltLength = 20; + + var hash_algo = "SHA-1"; + + if("hashAlgorithm" in pssParameters) + { + var hashAlgorithm = in_window.org.pkijs.getAlgorithmByOID(pssParameters.hashAlgorithm.algorithm_id); + if(("name" in hashAlgorithm) === false) + { + if(extendedMode) + { + return Promise.reject({ + date: checkDate, + code: 13, + message: "Unrecognized hash algorithm: " + pssParameters.hashAlgorithm.algorithm_id, + signatureVerified: null, + signerCertificate: signer_cert, + signerCertificateVerified: true + }); + } + + return Promise.reject("Unrecognized hash algorithm: " + pssParameters.hashAlgorithm.algorithm_id); + } + + hash_algo = hashAlgorithm.name; + } + + algorithm.algorithm.hash.name = hash_algo; + } + // #endregion + + // #region Special case for ECDSA signatures + var signature_value = signerInfos[signerIndex].signature.value_block.value_hex; + + if(publicKey.algorithm.name === "ECDSA") + { + var asn1 = in_window.org.pkijs.fromBER(signature_value); + signature_value = in_window.org.pkijs.createECDSASignatureFromCMS(asn1.result); + } + // #endregion + + return crypto.verify(algorithm.algorithm, + publicKey, + new Uint8Array(signature_value), + new Uint8Array(data)); + } + ); + // #endregion + + // #region Make a final result + sequence = sequence.then( + function(result) + { + if(extendedMode) + { + return { + date: checkDate, + code: 14, + message: "", + signatureVerified: result, + signerCertificate: signer_cert, + signerCertificateVerified: true + }; + } + + return result; + }, + function(error) + { + if(extendedMode) + { + if("code" in error) + return Promise.reject(error); + else + { + return Promise.reject({ + date: checkDate, + code: 15, + message: "Error during verification: " + error.message, + signatureVerified: null, + signerCertificate: signer_cert, + signerCertificateVerified: true + }); + } + } + + return Promise.reject(error); + } + ); + // #endregion + + return sequence; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_SIGNED_DATA.prototype.sign = + function(privateKey, signerIndex, hashAlgorithm, data) + { + /// Private key for "subjectPublicKeyInfo" structure + /// Index number (starting from 0) of signer index to make signature for + /// Hashing algorithm. Default SHA-1 + /// Detached data + + // #region Initial variables + var _this = this; + data = data || new ArrayBuffer(0); + var hashAlgorithmOID = ""; + // #endregion + + // #region Get a private key from function parameter + if(typeof privateKey === "undefined") + return Promise.reject("Need to provide a private key for signing"); + // #endregion + + // #region Get hashing algorithm + if(typeof hashAlgorithm === "undefined") + hashAlgorithm = "SHA-1"; + + // #region Simple check for supported algorithm + hashAlgorithmOID = in_window.org.pkijs.getOIDByAlgorithm({ name: hashAlgorithm }); + if(hashAlgorithmOID === "") + return Promise.reject("Unsupported hash algorithm: " + hashAlgorithm); + // #endregion + // #endregion + + // #region Append information about hash algorithm + var found = false; + + for(var i = 0; i < _this.digestAlgorithms.length; i++) + { + if(_this.digestAlgorithms[i].algorithm_id === hashAlgorithmOID) + { + found = true; + break; + } + } + + if(found === false) + { + _this.digestAlgorithms.push(new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: hashAlgorithmOID, + algorithm_params: new in_window.org.pkijs.asn1.NULL() + })); + } + + _this.signerInfos[signerIndex].digestAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: hashAlgorithmOID, + algorithm_params: new in_window.org.pkijs.asn1.NULL() + }); + // #endregion + + // #region Get a "default parameters" for current algorithm + var defParams = in_window.org.pkijs.getAlgorithmParameters(privateKey.algorithm.name, "sign"); + defParams.algorithm.hash.name = hashAlgorithm; + // #endregion + + // #region Fill internal structures base on "privateKey" and "hashAlgorithm" + switch(privateKey.algorithm.name.toUpperCase()) + { + case "RSASSA-PKCS1-V1_5": + case "ECDSA": + _this.signerInfos[signerIndex].signatureAlgorithm.algorithm_id = in_window.org.pkijs.getOIDByAlgorithm(defParams.algorithm); + break; + case "RSA-PSS": + { + // #region Set "saltLength" as a length (in octets) of hash function result + switch(hashAlgorithm.toUpperCase()) + { + case "SHA-256": + defParams.algorithm.saltLength = 32; + break; + case "SHA-384": + defParams.algorithm.saltLength = 48; + break; + case "SHA-512": + defParams.algorithm.saltLength = 64; + break; + default:; + } + // #endregion + + // #region Fill "RSASSA_PSS_params" object + var paramsObject = {}; + + if(hashAlgorithm.toUpperCase() !== "SHA-1") + { + hashAlgorithmOID = in_window.org.pkijs.getOIDByAlgorithm({ name: hashAlgorithm }); + if(hashAlgorithmOID === "") + return Promise.reject("Unsupported hash algorithm: " + hashAlgorithm); + + paramsObject.hashAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: hashAlgorithmOID, + algorithm_params: new in_window.org.pkijs.asn1.NULL() + }); + + paramsObject.maskGenAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: "1.2.840.113549.1.1.8", // MGF1 + algorithm_params: paramsObject.hashAlgorithm.toSchema() + }) + } + + if(defParams.algorithm.saltLength !== 20) + paramsObject.saltLength = defParams.algorithm.saltLength; + + var pssParameters = new in_window.org.pkijs.simpl.x509.RSASSA_PSS_params(paramsObject); + // #endregion + + // #region Automatically set signature algorithm + _this.signerInfos[signerIndex].signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: "1.2.840.113549.1.1.10", + algorithm_params: pssParameters.toSchema() + }); + // #endregion + } + break; + default: + return Promise.reject("Unsupported signature algorithm: " + privateKey.algorithm.name); + } + // #endregion + + // #region Create TBS data for signing + if("signedAttrs" in _this.signerInfos[signerIndex]) + { + if(_this.signerInfos[signerIndex].signedAttrs.encoded_value.byteLength !== 0) + data = _this.signerInfos[signerIndex].signedAttrs.encoded_value; + else + { + data = _this.signerInfos[signerIndex].signedAttrs.toSchema(true).toBER(false); + + // #region Change type from "[0]" to "SET" acordingly to standard + var view = new Uint8Array(data); + view[0] = 0x31; + // #endregion + } + } + else + { + if("eContent" in _this.encapContentInfo) // Attached data + { + if((_this.encapContentInfo.eContent.id_block.tag_class === 1) && + (_this.encapContentInfo.eContent.id_block.tag_number === 4)) + { + if(_this.encapContentInfo.eContent.id_block.is_constructed === false) + data = _this.encapContentInfo.eContent.value_block.value_hex; + else + { + for(var i = 0; i < _this.encapContentInfo.eContent.value_block.value.length; i++) + data = in_window.org.pkijs.concat_buffers(data, _this.encapContentInfo.eContent.value_block.value[i].value_block.value_hex); + } + } + else + data = _this.encapContentInfo.eContent.value_block.value_hex; + } + else // Detached data + { + if(data.byteLength === 0) // Check that "data" already provided by function parameter + return Promise.reject("Missed detached data input array"); + } + } + // #endregion + + // #region Get a "crypto" extension + var crypto = in_window.org.pkijs.getCrypto(); + if(typeof crypto == "undefined") + return Promise.reject("Unable to create WebCrypto object"); + // #endregion + + // #region Signing TBS data on provided private key + return crypto.sign(defParams.algorithm, + privateKey, + new Uint8Array(data)).then( + function(result) + { + // #region Special case for ECDSA algorithm + if(defParams.algorithm.name === "ECDSA") + result = in_window.org.pkijs.createCMSECDSASignature(result); + // #endregion + + _this.signerInfos[signerIndex].signature = new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: result }); + return Promise.resolve(result); + }, + function(error) + { + return Promise.reject("Signing error: " + error); + } + ); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_SIGNED_DATA.prototype.toJSON = + function() + { + var _object = { + version: this.version + }; + + _object.digestAlgorithms = new Array(); + + for(var i = 0; i < this.digestAlgorithms.length; i++) + _object.digestAlgorithms.push(this.digestAlgorithms[i].toJSON()); + + _object.encapContentInfo = this.encapContentInfo.toJSON(); + + if("certificates" in this) + { + _object.certificates = new Array(); + + for(var i = 0; i < this.certificates.length; i++) + _object.certificates.push(this.certificates[i].toJSON()); + } + + if("crls" in this) + { + _object.crls = new Array(); + + for(var i = 0; i < this.crls.length; i++) + _object.crls.push(this.crls[i].toJSON()); + } + + _object.signerInfos = new Array(); + + for(var i = 0; i < this.signerInfos.length; i++) + _object.signerInfos.push(this.signerInfos[i].toJSON()); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "ECC_CMS_SharedInfo" type + //************************************************************************************** + in_window.org.pkijs.simpl.cms.ECC_CMS_SharedInfo = + function() + { + // #region Internal properties of the object + this.keyInfo = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + // OPTIONAL this.entityUInfo = new in_window.org.pkijs.asn1.OCTETSTRING(); + this.suppPubInfo = new in_window.org.pkijs.asn1.OCTETSTRING(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.ECC_CMS_SharedInfo.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.keyInfo = arguments[0].keyInfo || (new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER()); + + if("entityUInfo" in arguments[0]) + this.entityUInfo = arguments[0].entityUInfo; + + this.suppPubInfo = arguments[0].suppPubInfo || (new in_window.org.pkijs.asn1.OCTETSTRING()); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.ECC_CMS_SharedInfo.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.ECC_CMS_SharedInfo({ + names: { + keyInfo: { + names: { + block_name: "keyInfo" + } + }, + entityUInfo: "entityUInfo", + suppPubInfo: "suppPubInfo" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for ECC_CMS_SharedInfo"); + // #endregion + + // #region Get internal properties from parsed schema + this.keyInfo = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["keyInfo"] }); + + if("entityUInfo" in asn1.result) + this.entityUInfo = asn1.result["entityUInfo"].value_block.value[0]; + + this.suppPubInfo = asn1.result["suppPubInfo"].value_block.value[0]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.ECC_CMS_SharedInfo.prototype.toSchema = + function() + { + // #region Create output array for sequence + var output_array = new Array(); + + output_array.push(this.keyInfo.toSchema()); + + if("entityUInfo" in this) + { + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [this.entityUInfo] + })); + } + + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 2 // [2] + }, + value: [this.suppPubInfo] + })); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + }); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.ECC_CMS_SharedInfo.prototype.toJSON = + function() + { + var _object = { + keyInfo: this.keyInfo.toJSON() + }; + + if("entityUInfo" in this) + _object.entityUInfo = this.entityUInfo.toJSON(); + + _object.suppPubInfo = this.suppPubInfo.toJSON(); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "RecipientIdentifier" type + //************************************************************************************** + in_window.org.pkijs.simpl.cms.RecipientIdentifier = + function() + { + // #region Internal properties of the object + this.variant = -1; // CHOICE variant + // VALUE OF CHOICE this.value + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.RecipientIdentifier.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.variant = arguments[0].variant || (-1); + + if("value" in arguments[0]) + this.value = arguments[0].value; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.RecipientIdentifier.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.RecipientIdentifier({ + names: { + block_name: "block_name" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for RecipientIdentifier"); + // #endregion + + // #region Get internal properties from parsed schema + if(asn1.result["block_name"].id_block.tag_class === 1) + { + this.variant = 1; + this.value = new in_window.org.pkijs.simpl.cms.IssuerAndSerialNumber({ schema: asn1.result["block_name"] }); + } + else + { + this.variant = 2; + this.value = asn1.result["block_name"].value_block.value[0]; + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.RecipientIdentifier.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + switch(this.variant) + { + case 1: + return this.value.toSchema(); + break; + case 2: + return new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [this.value] + }); + break; + default: + return new in_window.org.pkijs.asn1.ANY(); + } + // #endregion + + return new in_window.org.pkijs.asn1.ANY(); + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.RecipientIdentifier.prototype.toJSON = + function() + { + var _object = { + variant: this.variant + }; + + if((this.variant == 1) || (this.variant === 2)) + _object.value = this.value.toJSON(); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "KeyTransRecipientInfo" type + //************************************************************************************** + in_window.org.pkijs.simpl.cms.KeyTransRecipientInfo = + function() + { + // #region Internal properties of the object + this.version = -1; + this.rid = new in_window.org.pkijs.emptyObject(); + this.keyEncryptionAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.encryptedKey = new in_window.org.pkijs.asn1.OCTETSTRING(); + + this.recipientCertificate = new in_window.org.pkijs.simpl.CERT(); // For some reasons we need to store recipient's certificate here + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.KeyTransRecipientInfo.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.version = arguments[0].version || -1; + this.rid = arguments[0].rid || new in_window.org.pkijs.emptyObject(); + this.keyEncryptionAlgorithm = arguments[0].keyEncryptionAlgorithm || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.encryptedKey = arguments[0].encryptedKey || new in_window.org.pkijs.asn1.OCTETSTRING(); + + this.recipientCertificate = arguments[0].recipientCertificate || new in_window.org.pkijs.simpl.CERT(); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.KeyTransRecipientInfo.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.KeyTransRecipientInfo({ + names: { + version: "version", + rid: { + names: { + block_name: "rid" + } + }, + keyEncryptionAlgorithm: { + names: { + block_name: "keyEncryptionAlgorithm" + } + }, + encryptedKey: "encryptedKey" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for KeyTransRecipientInfo"); + // #endregion + + // #region Get internal properties from parsed schema + this.version = asn1.result["version"].value_block.value_dec; + + if(asn1.result["rid"].id_block.tag_class === 3) + this.rid = asn1.result["rid"].value_block.value[0]; // SubjectKeyIdentifier + else + this.rid = new in_window.org.pkijs.simpl.cms.IssuerAndSerialNumber({ schema: asn1.result["rid"] }); + + this.keyEncryptionAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["keyEncryptionAlgorithm"] }); + this.encryptedKey = asn1.result["encryptedKey"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.KeyTransRecipientInfo.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + if(this.rid instanceof in_window.org.pkijs.simpl.cms.IssuerAndSerialNumber) + { + this.version = 0; + + output_array.push(new in_window.org.pkijs.asn1.INTEGER({ value: this.version })); + output_array.push(this.rid.toSchema()); + } + else + { + this.version = 2; + + output_array.push(new in_window.org.pkijs.asn1.INTEGER({ value: this.version })); + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [this.rid] + })); + } + + output_array.push(this.keyEncryptionAlgorithm.toSchema()); + output_array.push(this.encryptedKey); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.KeyTransRecipientInfo.prototype.toJSON = + function() + { + return { + version: this.version, + rid: this.rid.toJSON(), + keyEncryptionAlgorithm: this.keyEncryptionAlgorithm.toJSON(), + encryptedKey: this.encryptedKey.toJSON() + }; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "OriginatorPublicKey" type + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OriginatorPublicKey = + function() + { + // #region Internal properties of the object + this.algorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.publicKey = new in_window.org.pkijs.asn1.BITSTRING(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.OriginatorPublicKey.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.algorithm = arguments[0].algorithm || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.publicKey = arguments[0].publicKey || new in_window.org.pkijs.asn1.BITSTRING(); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OriginatorPublicKey.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.OriginatorPublicKey({ + names: { + algorithm: { + names: { + block_name: "algorithm" + } + }, + publicKey: "publicKey" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for OriginatorPublicKey"); + // #endregion + + // #region Get internal properties from parsed schema + this.algorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["algorithm"] }); + this.publicKey = asn1.result["publicKey"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OriginatorPublicKey.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + this.algorithm.toSchema(), + this.publicKey + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OriginatorPublicKey.prototype.toJSON = + function() + { + return { + algorithm: this.algorithm.toJSON(), + publicKey: this.publicKey.toJSON() + }; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "OriginatorIdentifierOrKey" type + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OriginatorIdentifierOrKey = + function() + { + // #region Internal properties of the object + this.variant = -1; // CHOICE variant + // VALUE OF CHOICE this.value + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.OriginatorIdentifierOrKey.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.variant = arguments[0].variant || (-1); + + if("value" in arguments[0]) + this.value = arguments[0].value; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OriginatorIdentifierOrKey.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.OriginatorIdentifierOrKey({ + names: { + block_name: "block_name" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for OriginatorIdentifierOrKey"); + // #endregion + + // #region Get internal properties from parsed schema + if(asn1.result["block_name"].id_block.tag_class === 1) + { + this.variant = 1; + this.value = new in_window.org.pkijs.simpl.cms.IssuerAndSerialNumber({ schema: asn1.result["block_name"] }); + } + else + { + if(asn1.result["block_name"].id_block.tag_number === 0) + { + // #region Create "OCTETSTRING" from "ASN1_PRIMITIVE" + asn1.result["block_name"].id_block.tag_class = 1; // UNIVERSAL + asn1.result["block_name"].id_block.tag_number = 4; // OCTETSTRING + // #endregion + + this.variant = 2; + this.value = asn1.result["block_name"]; + } + else + { + // #region Create "SEQUENCE" from "ASN1_CONSTRUCTED" + asn1.result["block_name"].id_block.tag_class = 1; // UNIVERSAL + asn1.result["block_name"].id_block.tag_number = 16; // SEQUENCE + // #endregion + + this.variant = 3; + this.value = new in_window.org.pkijs.simpl.cms.OriginatorPublicKey({ schema: asn1.result["block_name"] }); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OriginatorIdentifierOrKey.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + switch(this.variant) + { + case 1: + return this.value.toSchema(); + break; + case 2: + { + this.value.id_block.tag_class = 3; // CONTEXT-SPECIFIC + this.value.id_block.tag_number = 0; // [0] + + return this.value; + } + break; + case 3: + { + var _schema = this.value.toSchema(); + + _schema.id_block.tag_class = 3; // CONTEXT-SPECIFIC + _schema.id_block.tag_number = 1; // [1] + + return _schema; + } + break; + default: + return new in_window.org.pkijs.asn1.ANY(); + } + // #endregion + + return new in_window.org.pkijs.asn1.ANY(); + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OriginatorIdentifierOrKey.prototype.toJSON = + function() + { + var _object = { + variant: this.variant + }; + + if((this.variant == 1) || (this.variant === 2) || (this.variant === 3)) + _object.value = this.value.toJSON(); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "OtherKeyAttribute" type + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OtherKeyAttribute = + function() + { + // #region Internal properties of the object + this.keyAttrId = ""; + // OPTIONAL this.keyAttr + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.OtherKeyAttribute.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.keyAttrId = arguments[0].keyAttrId || new in_window.org.pkijs.asn1.OID(); + + if("keyAttr" in arguments[0]) + this.keyAttr = arguments[0].keyAttr; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OtherKeyAttribute.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.OtherKeyAttribute({ + names: { + keyAttrId: "keyAttrId", + keyAttr: "keyAttr" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for OtherKeyAttribute"); + // #endregion + + // #region Get internal properties from parsed schema + this.keyAttrId = asn1.result["keyAttrId"].value_block.toString(); + + if("keyAttr" in asn1.result) + this.keyAttr = asn1.result["keyAttr"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OtherKeyAttribute.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + output_array.push(new in_window.org.pkijs.asn1.OID({ value: this.keyAttrId })); + + if("keyAttr" in this) + output_array.push(this.keyAttr.toSchema()); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OtherKeyAttribute.prototype.toJSON = + function() + { + var _object = { + keyAttrId: this.keyAttrId + }; + + if("keyAttr" in this) + _object.keyAttr = this.keyAttr.toJSON(); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "RecipientKeyIdentifier" type + //************************************************************************************** + in_window.org.pkijs.simpl.cms.RecipientKeyIdentifier = + function() + { + // #region Internal properties of the object + this.subjectKeyIdentifier = new in_window.org.pkijs.asn1.OCTETSTRING(); + // OPTIONAL this.date + // OPTIONAL this.other + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.RecipientKeyIdentifier.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.subjectKeyIdentifier = arguments[0].subjectKeyIdentifier || new in_window.org.pkijs.asn1.OCTETSTRING(); + + if("date" in arguments[0]) + this.date = arguments[0].date; + + if("other" in arguments[0]) + this.other = arguments[0].other; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.RecipientKeyIdentifier.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.RecipientKeyIdentifier({ + names: { + subjectKeyIdentifier: "subjectKeyIdentifier", + date: "date", + other: { + names: { + block_name: "other" + } + } + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for RecipientKeyIdentifier"); + // #endregion + + // #region Get internal properties from parsed schema + this.subjectKeyIdentifier = asn1.result["subjectKeyIdentifier"]; + + if("date" in asn1.result) + this.date = asn1.result["date"]; + + if("other" in asn1.result) + this.other = new in_window.org.pkijs.simpl.cms.OtherKeyAttribute({ schema: asn1.result["other"] }); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.RecipientKeyIdentifier.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + output_array.push(this.subjectKeyIdentifier); + + if("date" in this) + output_array.push(this.date); + + if("other" in this) + output_array.push(this.other.toSchema()); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.RecipientKeyIdentifier.prototype.toJSON = + function() + { + var _object = { + subjectKeyIdentifier: this.subjectKeyIdentifier.toJSON() + }; + + if("date" in this) + _object.date = this.date; + + if("other" in this) + _object.other = this.other.toJSON(); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "KeyAgreeRecipientIdentifier" type + //************************************************************************************** + in_window.org.pkijs.simpl.cms.KeyAgreeRecipientIdentifier = + function() + { + // #region Internal properties of the object + this.variant = -1; // CHOICE variant + // VALUE OF CHOICE this.value + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.KeyAgreeRecipientIdentifier.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.variant = arguments[0].variant || (-1); + + if("value" in arguments[0]) + this.value = arguments[0].value; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.KeyAgreeRecipientIdentifier.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.KeyAgreeRecipientIdentifier({ + names: { + block_name: "block_name" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for KeyAgreeRecipientIdentifier"); + // #endregion + + // #region Get internal properties from parsed schema + if(asn1.result["block_name"].id_block.tag_class === 1) + { + this.variant = 1; + this.value = new in_window.org.pkijs.simpl.cms.IssuerAndSerialNumber({ schema: asn1.result["block_name"] }); + } + else + { + this.variant = 2; + + asn1.result["block_name"].id_block.tag_class = 1; // UNIVERSAL + asn1.result["block_name"].id_block.tag_number = 16; // SEQUENCE + + this.value = new in_window.org.pkijs.simpl.cms.RecipientKeyIdentifier({ schema: asn1.result["block_name"] }); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.KeyAgreeRecipientIdentifier.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + switch(this.variant) + { + case 1: + return this.value.toSchema(); + break; + case 2: + return new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: this.value.toSchema().value_block.value + }); + break; + default: + return new in_window.org.pkijs.asn1.ANY(); + } + // #endregion + + return new in_window.org.pkijs.asn1.ANY(); + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.KeyAgreeRecipientIdentifier.prototype.toJSON = + function() + { + var _object = { + variant: this.variant + }; + + if((this.variant == 1) || (this.variant === 2)) + _object.value = this.value.toJSON(); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "RecipientEncryptedKey" type + //************************************************************************************** + in_window.org.pkijs.simpl.cms.RecipientEncryptedKey = + function() + { + // #region Internal properties of the object + this.rid = new in_window.org.pkijs.simpl.cms.KeyAgreeRecipientIdentifier(); + this.encryptedKey = new in_window.org.pkijs.asn1.OCTETSTRING(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.RecipientEncryptedKey.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.rid = arguments[0].rid || new in_window.org.pkijs.simpl.cms.KeyAgreeRecipientIdentifier(); + this.encryptedKey = arguments[0].encryptedKey || new in_window.org.pkijs.asn1.OCTETSTRING(); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.RecipientEncryptedKey.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.RecipientEncryptedKey({ + names: { + rid: { + names: { + block_name: "rid" + } + }, + encryptedKey: "encryptedKey" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for RecipientEncryptedKey"); + // #endregion + + // #region Get internal properties from parsed schema + this.rid = new in_window.org.pkijs.simpl.cms.KeyAgreeRecipientIdentifier({ schema: asn1.result["rid"] }); + this.encryptedKey = asn1.result["encryptedKey"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.RecipientEncryptedKey.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + this.rid.toSchema(), + this.encryptedKey + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.RecipientEncryptedKey.prototype.toJSON = + function() + { + return { + rid: this.rid.toJSON(), + encryptedKey: this.encryptedKey.toJSON() + }; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "RecipientEncryptedKeys" type + //************************************************************************************** + in_window.org.pkijs.simpl.cms.RecipientEncryptedKeys = + function() + { + // #region Internal properties of the object + this.encryptedKeys = new Array(); // Array of "in_window.org.pkijs.simpl.cms.RecipientEncryptedKey" + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.RecipientEncryptedKeys.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.encryptedKeys = arguments[0].encryptedKeys || new Array(); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.RecipientEncryptedKeys.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.RecipientEncryptedKeys({ + names: { + RecipientEncryptedKeys: "RecipientEncryptedKeys" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for RecipientEncryptedKeys"); + // #endregion + + // #region Get internal properties from parsed schema + var array = asn1.result["RecipientEncryptedKeys"]; + + for(var i = 0; i < array.length; i++) + this.encryptedKeys.push(new in_window.org.pkijs.simpl.cms.RecipientEncryptedKey({ schema: array[i] })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.RecipientEncryptedKeys.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + for(var i = 0; i < this.encryptedKeys.length; i++) + output_array.push(this.encryptedKeys[i].toSchema()); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.RecipientEncryptedKeys.prototype.toJSON = + function() + { + var _object = {}; + + _object.encryptedKeys = new Array(); + + for(var i = 0; i < this.encryptedKeys.length; i++) + _object.encryptedKeys.push(this.encryptedKeys[i].toJSON()); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "KeyAgreeRecipientInfo" type + //************************************************************************************** + in_window.org.pkijs.simpl.cms.KeyAgreeRecipientInfo = + function() + { + // #region Internal properties of the object + this.version = 0; + this.originator = new in_window.org.pkijs.simpl.cms.OriginatorIdentifierOrKey(); + // OPTIONAL this.ukm = new in_window.org.pkijs.asn1.OCTETSTRING(); + this.keyEncryptionAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.recipientEncryptedKeys = new in_window.org.pkijs.simpl.cms.RecipientEncryptedKeys(); + + this.recipientCertificate = new in_window.org.pkijs.simpl.CERT(); // For some reasons we need to store recipient's certificate here + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.KeyAgreeRecipientInfo.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.version = arguments[0].version || 0; + this.originator = arguments[0].originator || new in_window.org.pkijs.simpl.cms.OriginatorIdentifierOrKey(); + + if("ukm" in arguments[0]) + this.ukm = arguments[0].ukm; + + this.keyEncryptionAlgorithm = arguments[0].keyEncryptionAlgorithm || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.recipientEncryptedKeys = arguments[0].recipientEncryptedKeys || new in_window.org.pkijs.simpl.cms.RecipientEncryptedKeys(); + + this.recipientCertificate = arguments[0].recipientCertificate || new in_window.org.pkijs.simpl.CERT(); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.KeyAgreeRecipientInfo.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.KeyAgreeRecipientInfo({ + names: { + version: "version", + originator: { + names: { + block_name: "originator" + } + }, + ukm: "ukm", + keyEncryptionAlgorithm: { + names: { + block_name: "keyEncryptionAlgorithm" + } + }, + recipientEncryptedKeys: { + names: { + block_name: "recipientEncryptedKeys" + } + } + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for KeyAgreeRecipientInfo"); + // #endregion + + // #region Get internal properties from parsed schema + this.version = asn1.result["version"].value_block.value_dec; + this.originator = new in_window.org.pkijs.simpl.cms.OriginatorIdentifierOrKey({ schema: asn1.result["originator"] }); + + if("ukm" in asn1.result) + this.ukm = asn1.result["ukm"]; + + this.keyEncryptionAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["keyEncryptionAlgorithm"] }); + this.recipientEncryptedKeys = new in_window.org.pkijs.simpl.cms.RecipientEncryptedKeys({ schema: asn1.result["recipientEncryptedKeys"] }); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.KeyAgreeRecipientInfo.prototype.toSchema = + function() + { + // #region Create array for final sequence + var output_array = new Array(); + + output_array.push(new in_window.org.pkijs.asn1.INTEGER({ value: this.version })); + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [this.originator.toSchema()] + })); + + if("ukm" in this) + { + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [this.ukm] + })); + } + + output_array.push(this.keyEncryptionAlgorithm.toSchema()); + output_array.push(this.recipientEncryptedKeys.toSchema()); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.KeyAgreeRecipientInfo.prototype.toJSON = + function() + { + var _object = { + version: this.version, + originator: this.originator.toJSON() + }; + + if("ukm" in this) + _object.ukm = this.ukm.toJSON(); + + _object.keyEncryptionAlgorithm = this.keyEncryptionAlgorithm.toJSON(); + _object.recipientEncryptedKeys = this.recipientEncryptedKeys.toJSON(); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "KEKIdentifier" type + //************************************************************************************** + in_window.org.pkijs.simpl.cms.KEKIdentifier = + function() + { + // #region Internal properties of the object + this.keyIdentifier = new in_window.org.pkijs.asn1.OCTETSTRING(); + // OPTIONAL this.date + // OPTIONAL this.other + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.KEKIdentifier.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.keyIdentifier = arguments[0].keyIdentifier || new in_window.org.pkijs.asn1.OCTETSTRING(); + + if("date" in arguments[0]) + this.date = arguments[0].date; + + if("other" in arguments[0]) + this.other = arguments[0].other; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.KEKIdentifier.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.KEKIdentifier({ + names: { + keyIdentifier: "keyIdentifier", + date: "date", + other: { + names: { + block_name: "other" + } + } + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for KEKIdentifier"); + // #endregion + + // #region Get internal properties from parsed schema + this.keyIdentifier = asn1.result["keyIdentifier"]; + + if("date" in asn1.result) + this.date = asn1.result["date"]; + + if("other" in asn1.result) + this.other = new in_window.org.pkijs.simpl.cms.OtherKeyAttribute({ schema: asn1.result["other"] }); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.KEKIdentifier.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + output_array.push(this.keyIdentifier); + + if("date" in this) + output_array.push(this.date); + + if("other" in this) + output_array.push(this.other.toSchema()); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.KEKIdentifier.prototype.toJSON = + function() + { + var _object = { + keyIdentifier: this.keyIdentifier.toJSON() + }; + + if("date" in this) + _object.date = this.date; + + if("other" in this) + _object.other = this.other.toJSON(); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "KEKRecipientInfo" type + //************************************************************************************** + in_window.org.pkijs.simpl.cms.KEKRecipientInfo = + function() + { + // #region Internal properties of the object + this.version = 0; + this.kekid = new in_window.org.pkijs.simpl.cms.KEKIdentifier(); + this.keyEncryptionAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.encryptedKey = new in_window.org.pkijs.asn1.OCTETSTRING(); + + this.preDefinedKEK = new ArrayBuffer(0); // KEK using to encrypt CEK + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.KEKRecipientInfo.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.version = arguments[0].version || 0; + this.kekid = arguments[0].kekid || new in_window.org.pkijs.simpl.cms.KEKIdentifier(); + this.keyEncryptionAlgorithm = arguments[0].keyEncryptionAlgorithm || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.encryptedKey = arguments[0].encryptedKey || new in_window.org.pkijs.asn1.OCTETSTRING(); + + this.preDefinedKEK = arguments[0].preDefinedKEK || new ArrayBuffer(0); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.KEKRecipientInfo.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.KEKRecipientInfo({ + names: { + version: "version", + kekid: { + names: { + block_name: "kekid" + } + }, + keyEncryptionAlgorithm: { + names: { + block_name: "keyEncryptionAlgorithm" + } + }, + encryptedKey: "encryptedKey" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for KEKRecipientInfo"); + // #endregion + + // #region Get internal properties from parsed schema + this.version = asn1.result["version"].value_block.value_dec; + this.kekid = new in_window.org.pkijs.simpl.cms.KEKIdentifier({ schema: asn1.result["kekid"] }); + this.keyEncryptionAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["keyEncryptionAlgorithm"] }); + this.encryptedKey = asn1.result["encryptedKey"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.KEKRecipientInfo.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + new in_window.org.pkijs.asn1.INTEGER({ value: this.version }), + this.kekid.toSchema(), + this.keyEncryptionAlgorithm.toSchema(), + this.encryptedKey + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.KEKRecipientInfo.prototype.toJSON = + function() + { + return { + version: this.version, + kekid: this.originator.toJSON(), + keyEncryptionAlgorithm: this.keyEncryptionAlgorithm.toJSON(), + encryptedKey: this.encryptedKey.toJSON() + }; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "PasswordRecipientinfo" type + //************************************************************************************** + in_window.org.pkijs.simpl.cms.PasswordRecipientinfo = + function() + { + // #region Internal properties of the object + this.version = -1; + // OPTIONAL this.keyDerivationAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.keyEncryptionAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.encryptedKey = new in_window.org.pkijs.asn1.OCTETSTRING(); + + this.password = new ArrayBuffer(0); // Password to derive key from + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.PasswordRecipientinfo.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + if("version" in arguments[0]) + this.version = arguments[0].version; + else + this.version = -1; + + if("keyDerivationAlgorithm" in arguments[0]) + this.keyDerivationAlgorithm = arguments[0].keyDerivationAlgorithm; + + this.keyEncryptionAlgorithm = arguments[0].keyEncryptionAlgorithm || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.encryptedKey = arguments[0].encryptedKey || new in_window.org.pkijs.asn1.OCTETSTRING(); + + this.password = arguments[0].password || new ArrayBuffer(0); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.PasswordRecipientinfo.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.PasswordRecipientinfo({ + names: { + version: "version", + keyDerivationAlgorithm: "keyDerivationAlgorithm", + keyEncryptionAlgorithm: { + names: { + block_name: "keyEncryptionAlgorithm" + } + }, + encryptedKey: "encryptedKey" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for PasswordRecipientinfo"); + // #endregion + + // #region Get internal properties from parsed schema + this.version = asn1.result["version"].value_block.value_dec; + + if("keyDerivationAlgorithm" in asn1.result) + { + asn1.result["keyDerivationAlgorithm"].id_block.tag_class = 1; // UNIVERSAL + asn1.result["keyDerivationAlgorithm"].id_block.tag_number = 16; // SEQUENCE + + this.keyDerivationAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["keyDerivationAlgorithm"] }); + } + + this.keyEncryptionAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["keyEncryptionAlgorithm"] }); + this.encryptedKey = asn1.result["encryptedKey"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.PasswordRecipientinfo.prototype.toSchema = + function() + { + // #region Create output array for sequence + var output_array = new Array(); + + output_array.push(new in_window.org.pkijs.asn1.INTEGER({ value: this.version })); + + if("keyDerivationAlgorithm" in this) + { + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: this.keyDerivationAlgorithm.toSchema().value_block.value + })); + } + + output_array.push(this.keyEncryptionAlgorithm.toSchema()); + output_array.push(this.encryptedKey); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.PasswordRecipientinfo.prototype.toJSON = + function() + { + return { + version: this.version, + keyDerivationAlgorithm: this.keyDerivationAlgorithm.toJSON(), + keyEncryptionAlgorithm: this.keyEncryptionAlgorithm.toJSON(), + encryptedKey: this.encryptedKey.toJSON() + }; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "OtherRecipientInfo" type + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OtherRecipientInfo = + function() + { + // #region Internal properties of the object + this.oriType = ""; + this.oriValue = new in_window.org.pkijs.asn1.ANY(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.OtherRecipientInfo.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.oriType = arguments[0].oriType || ""; + this.oriValue = arguments[0].oriValue || new in_window.org.pkijs.asn1.ANY(); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OtherRecipientInfo.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.OtherRecipientInfo({ + names: { + oriType: "oriType", + oriValue: "oriValue" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for OtherRecipientInfo"); + // #endregion + + // #region Get internal properties from parsed schema + this.oriType = asn1.result["oriType"].value_block.toString(); + this.oriValue = asn1.result["oriValue"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OtherRecipientInfo.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + new in_window.org.pkijs.asn1.OID({ value: this.oriType }), + this.oriValue + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OtherRecipientInfo.prototype.toJSON = + function() + { + var _object = { + oriType: this.oriType + }; + + if(!(this.oriValue instanceof in_window.org.pkijs.asn1.ANY)) + _object.oriValue = this.oriValue.toJSON(); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "CMS_RECIPIENT_INFO" type + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_RECIPIENT_INFO = + function() + { + // #region Internal properties of the object + this.variant = -1; // CHOICE variant + // VALUE OF CHOICE this.value + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.CMS_RECIPIENT_INFO.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.variant = arguments[0].variant || (-1); + + if("value" in arguments[0]) + this.value = arguments[0].value; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_RECIPIENT_INFO.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.CMS_RECIPIENT_INFO({ + names: { + block_name: "block_name" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for CMS_RECIPIENT_INFO"); + // #endregion + + // #region Get internal properties from parsed schema + if(asn1.result["block_name"].id_block.tag_class === 1) + { + this.variant = 1; + this.value = new in_window.org.pkijs.simpl.cms.KeyTransRecipientInfo({ schema: asn1.result["block_name"] }); + } + else + { + // #region Create "SEQUENCE" from "ASN1_CONSTRUCTED" + var _tag_number = asn1.result["block_name"].id_block.tag_number; + + asn1.result["block_name"].id_block.tag_class = 1; // UNIVERSAL + asn1.result["block_name"].id_block.tag_number = 16; // SEQUENCE + // #endregion + + switch(_tag_number) + { + case 1: + this.variant = 2; + this.value = new in_window.org.pkijs.simpl.cms.KeyAgreeRecipientInfo({ schema: asn1.result["block_name"] }); + break; + case 2: + this.variant = 3; + this.value = new in_window.org.pkijs.simpl.cms.KEKRecipientInfo({ schema: asn1.result["block_name"] }); + break; + case 3: + this.variant = 4; + this.value = new in_window.org.pkijs.simpl.cms.PasswordRecipientinfo({ schema: asn1.result["block_name"] }); + break; + case 4: + this.variant = 5; + this.value = new in_window.org.pkijs.simpl.cms.OtherRecipientInfo({ schema: asn1.result["block_name"] }); + break; + default:; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_RECIPIENT_INFO.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + var _schema = this.value.toSchema(); + + switch(this.variant) + { + case 1: + return _schema; + break; + case 2: + case 3: + case 4: + { + // #region Create "ASN1_CONSTRUCTED" from "SEQUENCE" + _schema.id_block.tag_class = 3; // CONTEXT-SPECIFIC + _schema.id_block.tag_number = (this.variant - 1); + // #endregion + + return _schema; + } + break; + default: + return new in_window.org.pkijs.asn1.ANY(); + } + // #endregion + + return new in_window.org.pkijs.asn1.ANY(); + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_RECIPIENT_INFO.prototype.toJSON = + function() + { + var _object = { + variant: this.variant + }; + + if((this.variant >= 1) && (this.variant <= 4)) + _object.value = this.value.toJSON(); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "OriginatorInfo" type + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OriginatorInfo = + function() + { + // #region Internal properties of the object + this.certs = new in_window.org.pkijs.simpl.CMS_CERTIFICATE_SET(); + this.crls = new in_window.org.pkijs.simpl.CMS_REVOCATION_INFO_CHOICES(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.OriginatorInfo.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.certs = arguments[0].certs || new in_window.org.pkijs.simpl.CMS_CERTIFICATE_SET(); + this.crls = arguments[0].crls || new in_window.org.pkijs.simpl.CMS_REVOCATION_INFO_CHOICES(); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OriginatorInfo.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.OriginatorInfo({ + names: { + certs: "certs", + crls: "crls" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for OriginatorInfo"); + // #endregion + + // #region Get internal properties from parsed schema + asn1.result["certs"].id_block.tag_class = 1; // UNIVERSAL + asn1.result["certs"].id_block.tag_number = 17; // SET + + this.certs = new in_window.org.pkijs.simpl.CMS_CERTIFICATE_SET({ schema: asn1.result["certs"] }); + + asn1.result["crls"].id_block.tag_class = 1; // UNIVERSAL + asn1.result["crls"].id_block.tag_number = 17; // SET + + this.crls = new in_window.org.pkijs.simpl.CMS_REVOCATION_INFO_CHOICES({ schema: asn1.result["crls"] }); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OriginatorInfo.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: this.certs.toSchema().value_block.value + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: this.crls.toSchema().value_block.value + }) + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.OriginatorInfo.prototype.toJSON = + function() + { + return { + certs: this.certs.toJSON(), + crls: this.crls.toJSON() + }; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "EncryptedContentInfo" type + //************************************************************************************** + in_window.org.pkijs.simpl.cms.EncryptedContentInfo = + function() + { + // #region Internal properties of the object + this.contentType = ""; + this.contentEncryptionAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + // OPTIONAL this.encryptedContent // new in_window.org.pkijs.asn1.OCTETSTRING - (!!!) could be contructive or primitive value (!!!) + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.cms.EncryptedContentInfo.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.contentType = arguments[0].contentType || ""; + this.contentEncryptionAlgorithm = arguments[0].contentEncryptionAlgorithm || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + + if("encryptedContent" in arguments[0]) + { + this.encryptedContent = arguments[0].encryptedContent; + + if((this.encryptedContent.id_block.tag_class === 1) && + (this.encryptedContent.id_block.tag_number === 4)) + { + // #region Divide OCTETSTRING value down to small pieces + if(this.encryptedContent.id_block.is_constructed === false) + { + var constr_string = new in_window.org.pkijs.asn1.OCTETSTRING({ + id_block: { is_constructed: true }, + is_constructed: true + }); + + var offset = 0; + var length = this.encryptedContent.value_block.value_hex.byteLength; + + while(length > 0) + { + var piece_view = new Uint8Array(this.encryptedContent.value_block.value_hex, offset, ((offset + 1024) > this.encryptedContent.value_block.value_hex.byteLength) ? (this.encryptedContent.value_block.value_hex.byteLength - offset) : 1024); + var _array = new ArrayBuffer(piece_view.length); + var _view = new Uint8Array(_array); + + for(var i = 0; i < _view.length; i++) + _view[i] = piece_view[i]; + + constr_string.value_block.value.push(new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: _array })); + + length -= piece_view.length; + offset += piece_view.length; + } + + this.encryptedContent = constr_string; + } + // #endregion + } + } + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.EncryptedContentInfo.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.cms.EncryptedContentInfo({ + names: { + contentType: "contentType", + contentEncryptionAlgorithm: { + names: { + block_name: "contentEncryptionAlgorithm" + } + }, + encryptedContent: "encryptedContent" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for EncryptedContentInfo"); + // #endregion + + // #region Get internal properties from parsed schema + this.contentType = asn1.result["contentType"].value_block.toString(); + this.contentEncryptionAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["contentEncryptionAlgorithm"] }); + + if("encryptedContent" in asn1.result) + { + this.encryptedContent = asn1.result["encryptedContent"]; + + this.encryptedContent.id_block.tag_class = 1; // UNIVERSAL + this.encryptedContent.id_block.tag_number = 4; // OCTETSTRING (!!!) The value still has instance of "in_window.org.pkijs.asn1.ASN1_CONSTRUCTED / ASN1_PRIMITIVE" + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.EncryptedContentInfo.prototype.toSchema = + function() + { + // #region Create array for output sequence + var sequenceLengthBlock = { + is_indefinite_form: false + }; + + var output_array = new Array(); + + output_array.push(new in_window.org.pkijs.asn1.OID({ value: this.contentType })); + output_array.push(this.contentEncryptionAlgorithm.toSchema()); + + if("encryptedContent" in this) + { + sequenceLengthBlock.is_indefinite_form = this.encryptedContent.id_block.is_constructed; + + var encryptedValue = this.encryptedContent; + + encryptedValue.id_block.tag_class = 3; // CONTEXT-SPECIFIC + encryptedValue.id_block.tag_number = 0; // [0] + + encryptedValue.len_block.is_indefinite_form = this.encryptedContent.id_block.is_constructed; + + output_array.push(encryptedValue); + } + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + len_block: sequenceLengthBlock, + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.cms.EncryptedContentInfo.prototype.toJSON = + function() + { + var _object = { + contentType: this.contentType, + contentEncryptionAlgorithm: this.contentEncryptionAlgorithm.toJSON() + }; + + if("encryptedContent" in this) + _object.encryptedContent = this.encryptedContent.toJSON(); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "CMS_ENVELOPED_DATA" type + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_ENVELOPED_DATA = + function() + { + // #region Internal properties of the object + this.version = 0; + // OPTIONAL this.originatorInfo + this.recipientInfos = new Array(); // Array of "simpl.CMS_RECIPIENT_INFO" + this.encryptedContentInfo = new in_window.org.pkijs.simpl.cms.EncryptedContentInfo(); + // OPTIONAL this.unprotectedAttrs + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.CMS_ENVELOPED_DATA.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.version = arguments[0].version || 0; + + if("originatorInfo" in arguments[0]) + this.originatorInfo = arguments[0].originatorInfo; + + this.recipientInfos = arguments[0].recipientInfos || new Array(); // Array of "simpl.CMS_RECIPIENT_INFO" + this.encryptedContentInfo = arguments[0].encryptedContentInfo || new in_window.org.pkijs.simpl.cms.EncryptedContentInfo(); + + if("unprotectedAttrs" in arguments[0]) + this.unprotectedAttrs = arguments[0].unprotectedAttrs; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_ENVELOPED_DATA.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.CMS_ENVELOPED_DATA({ + names: { + version: "version", + originatorInfo: "originatorInfo", + recipientInfos: "recipientInfos", + encryptedContentInfo: { + names: { + block_name: "encryptedContentInfo" + } + }, + unprotectedAttrs: "unprotectedAttrs" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for CMS_ENVELOPED_DATA"); + // #endregion + + // #region Get internal properties from parsed schema + this.version = asn1.result["version"].value_block.value_dec; + + if("originatorInfo" in asn1.result) + { + asn1.result["originatorInfo"].id_block.tag_class = 1; // UNIVERSAL + asn1.result["originatorInfo"].id_block.tag_number = 16; // SEQUENCE + + this.originatorInfo = new in_window.org.pkijs.simpl.cms.OriginatorInfo({ schema: asn1.result["originatorInfo"] }); + } + + var recipient_array = asn1.result["recipientInfos"]; + + for(var i = 0; i < recipient_array.length; i++) + this.recipientInfos.push(new in_window.org.pkijs.simpl.CMS_RECIPIENT_INFO({ schema: recipient_array[i] })); + + this.encryptedContentInfo = new in_window.org.pkijs.simpl.cms.EncryptedContentInfo({ schema: asn1.result["encryptedContentInfo"] }); + + if("unprotectedAttrs" in asn1.result) + { + this.unprotectedAttrs = new Array(); + var attributes_array = asn1.result["unprotectedAttrs"]; + + for(var j = 0; j < attributes_array.length; j++) + this.unprotectedAttrs.push(new in_window.org.pkijs.simpl.ATTRIBUTE({ schema: attributes_array[j] })); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_ENVELOPED_DATA.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + output_array.push(new in_window.org.pkijs.asn1.INTEGER({ value: this.version })); + + if("originatorInfo" in this) + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: this.originatorInfo.toSchema().value_block.value + })); + + var recipients = new Array(); + + for(var i = 0; i < this.recipientInfos.length; i++) + recipients.push(this.recipientInfos[i].toSchema()); + + output_array.push(new in_window.org.pkijs.asn1.SET({ + value: recipients + })); + + output_array.push(this.encryptedContentInfo.toSchema()); + + if("unprotectedAttrs" in this) + { + var attributes = new Array(); + + for(var j = 0; j < this.unprotectedAttrs.length; j++) + attributes.push(this.unprotectedAttrs[j].toSchema()); + + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: attributes + })); + } + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_ENVELOPED_DATA.prototype.toJSON = + function() + { + var _object = { + version: this.version + }; + + if("originatorInfo" in this) + _object.originatorInfo = this.originatorInfo.toJSON(); + + _object.recipientInfos = new Array(); + + for(var i = 0; i < this.recipientInfos.length; i++) + _object.recipientInfos.push(this.recipientInfos[i].toJSON()); + + _object.encryptedContentInfo = this.encryptedContentInfo.toJSON(); + + if("unprotectedAttrs" in this) + { + _object.unprotectedAttrs = new Array(); + + for(var i = 0; i < this.unprotectedAttrs.length; i++) + _object.unprotectedAttrs.push(this.unprotectedAttrs[i].toJSON()); + } + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_ENVELOPED_DATA.prototype.addRecipientByCertificate = + function(certificate, parameters, variant) + { + /// + /// Helpers function for filling "RecipientInfo" based on recipient's certificate. + /// Problem with WebCrypto is that for RSA certificates we have only one option - "key transport" and + /// for ECC certificates we also have one option - "key agreement". As soon as Google will implement + /// DH algorithm it would be possible to use "key agreement" also for RSA certificates. + /// + /// Recipient's certificate + /// Additional parameters neccessary for "fine tunning" of encryption process + /// + /// Variant = 1 is for "key transport", variant = 2 is for "key agreement". + /// In fact the "variant" is unneccessary now because Google has no DH algorithm implementation. + /// Thus key encryption scheme would be choosen by certificate type only: "key transport" for RSA and "key agreement" for ECC certificates. + /// + + // #region Initial variables + var certificateType = 0; + var encryptionParameters = parameters || {}; + // #endregion + + // #region Check type of certificate + if(certificate.subjectPublicKeyInfo.algorithm.algorithm_id.indexOf("1.2.840.113549") !== (-1)) + { + certificateType = 1; // RSA-based certificate + variant = 1; // For the moment it is the only variant for RSA-based certificates + } + else + { + if(certificate.subjectPublicKeyInfo.algorithm.algorithm_id.indexOf("1.2.840.10045") !== (-1)) + { + certificateType = 2; // ECC-based certificate + variant = 2; // For the moment it is the only variant for ECC-based certificates + } + else + throw new Error("Unknown type of certificate's public key: " + certificate.subjectPublicKeyInfo.algorithm.algorithm_id); + } + // #endregion + + // #region Initialize encryption parameters + if(("oaepHashAlgorithm" in encryptionParameters) === false) + encryptionParameters.oaepHashAlgorithm = "SHA-512"; + + if(("kdfAlgorithm" in encryptionParameters) === false) + encryptionParameters.kdfAlgorithm = "SHA-512"; + + if(("kekEncryptionLength" in encryptionParameters) === false) + encryptionParameters.kekEncryptionLength = 256; + // #endregion + + // #region Add new "recipient" depends on "variant" and certificate type + switch(variant) + { + case 1: // Key transport scheme + { + // #region keyEncryptionAlgorithm + var oaepOID = in_window.org.pkijs.getOIDByAlgorithm({ + name: "RSA-OAEP" + }); + if(oaepOID === "") + throw new Error("Can not find OID for OAEP"); + // #endregion + + // #region RSAES-OAEP-params + var hashOID = in_window.org.pkijs.getOIDByAlgorithm({ + name: encryptionParameters.oaepHashAlgorithm + }); + if(hashOID === "") + throw new Error("Unknown OAEP hash algorithm: " + encryptionParameters.oaepHashAlgorithm); + + var hashAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: hashOID, + algorithm_params: new in_window.org.pkijs.asn1.NULL() + }); + + var rsaOAEPParams = new in_window.org.pkijs.simpl.cms.RSAES_OAEP_params({ + hashAlgorithm: hashAlgorithm, + maskGenAlgorithm: new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: "1.2.840.113549.1.1.8", // id-mgf1 + algorithm_params: hashAlgorithm.toSchema() + }) + }); + // #endregion + + // #region KeyTransRecipientInfo + var keyInfo = new in_window.org.pkijs.simpl.cms.KeyTransRecipientInfo({ + version: 0, + rid: new in_window.org.pkijs.simpl.cms.IssuerAndSerialNumber({ + issuer: certificate.issuer, + serialNumber: certificate.serialNumber + }), + keyEncryptionAlgorithm: new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: oaepOID, + algorithm_params: rsaOAEPParams.toSchema() + }), + recipientCertificate: certificate + // "encryptedKey" will be calculated in "encrypt" function + }); + // #endregion + + // #region Final values for "CMS_ENVELOPED_DATA" + this.recipientInfos.push(new in_window.org.pkijs.simpl.CMS_RECIPIENT_INFO({ + variant: 1, + value: keyInfo + })); + // #endregion + } + break; + case 2: // Key agreement scheme + { + // #region RecipientEncryptedKey + var encryptedKey = new in_window.org.pkijs.simpl.cms.RecipientEncryptedKey({ + rid: new in_window.org.pkijs.simpl.cms.KeyAgreeRecipientIdentifier({ + variant: 1, + value: new in_window.org.pkijs.simpl.cms.IssuerAndSerialNumber({ + issuer: certificate.issuer, + serialNumber: certificate.serialNumber + }) + }) + // "encryptedKey" will be calculated in "encrypt" function + }); + // #endregion + + // #region keyEncryptionAlgorithm + var aesKWoid = in_window.org.pkijs.getOIDByAlgorithm({ + name: "AES-KW", + length: encryptionParameters.kekEncryptionLength + }); + if(aesKWoid === "") + throw new Error("Unknown length for key encryption algorithm: " + encryptionParameters.kekEncryptionLength); + + var aesKW = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: aesKWoid, + algorithm_params: new in_window.org.pkijs.asn1.NULL() + }); + // #endregion + + // #region KeyAgreeRecipientInfo + var ecdhOID = in_window.org.pkijs.getOIDByAlgorithm({ + name: "ECDH", + kdf: encryptionParameters.kdfAlgorithm + }); + if(ecdhOID === "") + throw new Error("Unknown KDF algorithm: " + encryptionParameters.kdfAlgorithm); + + // In fact there is no need in so long UKM, but RFC2631 + // has requirement that "UserKeyMaterial" must be 512 bits long + var ukmBuffer = new ArrayBuffer(64); + var ukmView = new Uint8Array(ukmBuffer); + in_window.org.pkijs.getRandomValues(ukmView); // Generate random values in 64 bytes long buffer + + var keyInfo = new in_window.org.pkijs.simpl.cms.KeyAgreeRecipientInfo({ + version: 3, + // "originator" will be calculated in "encrypt" function because ephemeral key would be generated there + ukm: new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: ukmBuffer }), + keyEncryptionAlgorithm: new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: ecdhOID, + algorithm_params: aesKW.toSchema() + }), + recipientEncryptedKeys: new in_window.org.pkijs.simpl.cms.RecipientEncryptedKeys({ + encryptedKeys: [encryptedKey] + }), + recipientCertificate: certificate + }); + // #endregion + + // #region Final values for "CMS_ENVELOPED_DATA" + this.recipientInfos.push(new in_window.org.pkijs.simpl.CMS_RECIPIENT_INFO({ + variant: 2, + value: keyInfo + })); + // #endregion + } + break; + default: + throw new Error("Unknown \"variant\" value: " + variant); + } + // #endregion + + return true; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_ENVELOPED_DATA.prototype.addRecipientByPreDefinedData = + function(preDefinedData, parameters, variant) + { + /// Add recipient based on pre-defined data like password or KEK + /// ArrayBuffer with pre-defined data + /// Additional parameters neccessary for "fine tunning" of encryption process + /// + /// Variant = 1 for pre-defined "key encryption key" (KEK). + /// Variant = 2 for password-based encryption. + /// + + // #region Initial variables + var encryptionParameters = parameters || {}; + // #endregion + + // #region Check initial parameters + if((preDefinedData instanceof ArrayBuffer) === false) + throw new Error("Please pass \"preDefinedData\" in ArrayBuffer type"); + + if(preDefinedData.byteLength === 0) + throw new Error("Pre-defined data could have zero length"); + // #endregion + + // #region Initialize encryption parameters + if(("keyIdentifier" in encryptionParameters) === false) + { + var keyIdentifierBuffer = new ArrayBuffer(16); + var keyIdentifierView = new Uint8Array(keyIdentifierBuffer); + in_window.org.pkijs.getRandomValues(keyIdentifierView); + + encryptionParameters.keyIdentifier = keyIdentifierBuffer; + } + + if(("hmacHashAlgorithm" in encryptionParameters) === false) + encryptionParameters.hmacHashAlgorithm = "SHA-512"; + + if(("iterationCount" in encryptionParameters) === false) + encryptionParameters.iterationCount = 2048; + + if(("keyEncryptionAlgorithm" in encryptionParameters) === false) + { + encryptionParameters.keyEncryptionAlgorithm = { + name: "AES-KW", + length: 256 + }; + } + + if(("keyEncryptionAlgorithmParams" in encryptionParameters) === false) + encryptionParameters.keyEncryptionAlgorithmParams = new in_window.org.pkijs.asn1.NULL(); + // #endregion + + // #region Add new recipient based on passed variant + switch(variant) + { + case 1: // KEKRecipientInfo + { + // #region keyEncryptionAlgorithm + var kekOID = in_window.org.pkijs.getOIDByAlgorithm(encryptionParameters.keyEncryptionAlgorithm); + if(kekOID === "") + throw new Error("Incorrect value for \"keyEncryptionAlgorithm\""); + // #endregion + + // #region KEKRecipientInfo + var keyInfo = new in_window.org.pkijs.simpl.cms.KEKRecipientInfo({ + version: 4, + kekid: new in_window.org.pkijs.simpl.cms.KEKIdentifier({ + keyIdentifier: new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: encryptionParameters.keyIdentifier }) + }), + keyEncryptionAlgorithm: new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: kekOID, + /* + For AES-KW params are NULL, but for other algorithm could another situation. + */ + algorithm_params: encryptionParameters.keyEncryptionAlgorithmParams + }), + preDefinedKEK: preDefinedData + // "encryptedKey" would be set in "ecrypt" function + }); + // #endregion + + // #region Final values for "CMS_ENVELOPED_DATA" + this.recipientInfos.push(new in_window.org.pkijs.simpl.CMS_RECIPIENT_INFO({ + variant: 3, + value: keyInfo + })); + // #endregion + } + break; + case 2: // PasswordRecipientinfo + { + // #region keyDerivationAlgorithm + var pbkdf2OID = in_window.org.pkijs.getOIDByAlgorithm({ + name: "PBKDF2" + }); + if(pbkdf2OID === "") + throw new Error("Can not find OID for PBKDF2"); + // #endregion + + // #region Salt + var saltBuffer = new ArrayBuffer(64); + var saltView = new Uint8Array(saltBuffer); + in_window.org.pkijs.getRandomValues(saltView); + // #endregion + + // #region HMAC-based algorithm + var hmacOID = in_window.org.pkijs.getOIDByAlgorithm({ + name: "HMAC", + hash: { + name: encryptionParameters.hmacHashAlgorithm + } + }); + if(hmacOID === "") + throw new Error("Incorrect value for \"hmacHashAlgorithm\": " + encryptionParameters.hmacHashAlgorithm); + // #endregion + + // #region PBKDF2-params + var pbkdf2Params = new in_window.org.pkijs.simpl.cms.PBKDF2_params({ + salt: new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: saltBuffer }), + iterationCount: encryptionParameters.iterationCount, + prf: new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: hmacOID, + algorithm_params: new in_window.org.pkijs.asn1.NULL() + }) + }); + // #endregion + + // #region keyEncryptionAlgorithm + var kekOID = in_window.org.pkijs.getOIDByAlgorithm(encryptionParameters.keyEncryptionAlgorithm); + if(kekOID === "") + throw new Error("Incorrect value for \"keyEncryptionAlgorithm\""); + // #endregion + + // #region PasswordRecipientinfo + var keyInfo = new in_window.org.pkijs.simpl.cms.PasswordRecipientinfo({ + version: 0, + keyDerivationAlgorithm: new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: pbkdf2OID, + algorithm_params: pbkdf2Params.toSchema() + }), + keyEncryptionAlgorithm: new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: kekOID, + /* + For AES-KW params are NULL, but for other algorithm could be another situation. + */ + algorithm_params: encryptionParameters.keyEncryptionAlgorithmParams + }), + password: preDefinedData + // "encryptedKey" would be set in "ecrypt" function + }); + // #endregion + + // #region Final values for "CMS_ENVELOPED_DATA" + this.recipientInfos.push(new in_window.org.pkijs.simpl.CMS_RECIPIENT_INFO({ + variant: 4, + value: keyInfo + })); + // #endregion + } + break; + default: + throw new Error("Unknown value for \"variant\": " + variant); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_ENVELOPED_DATA.prototype.encrypt = + function(contentEncryptionAlgorithm, contentToEncrypt) + { + /// Create a new CMS Enveloped Data content with encrypted data + /// + /// WebCrypto algorithm. For the moment here could be only "AES-CBC" or "AES-GCM" algorithms. + /// + /// Content to encrypt + + // #region Initial variables + var _this = this; + var sequence = Promise.resolve(); + + var ivBuffer = new ArrayBuffer(16); // For AES we need IV 16 bytes long + var ivView = new Uint8Array(ivBuffer); + in_window.org.pkijs.getRandomValues(ivView); + + var contentView = new Uint8Array(contentToEncrypt); + + var sessionKey; + var encryptedContent; + var exportedSessionKey; + + var recipientsPromises = new Array(); + // #endregion + + // #region Check for input parameters + var contentEncryptionOID = in_window.org.pkijs.getOIDByAlgorithm(contentEncryptionAlgorithm); + if(contentEncryptionOID === "") + return Promise.reject("Wrong \"contentEncryptionAlgorithm\" value"); + // #endregion + + // #region Get a "crypto" extension + var crypto = in_window.org.pkijs.getCrypto(); + if(typeof crypto == "undefined") + return Promise.reject("Unable to create WebCrypto object"); + // #endregion + + // #region Generate new content encryption key + sequence = sequence.then( + function(result) + { + return crypto.generateKey(contentEncryptionAlgorithm, true, ["encrypt"]); + } + ); + // #endregion + // #region Encrypt content + sequence = sequence.then( + function(result) + { + sessionKey = result; + + return crypto.encrypt({ + name: contentEncryptionAlgorithm.name, + iv: ivView + }, + sessionKey, + contentView); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Export raw content of content encryption key + sequence = sequence.then( + function(result) + { + // #region Create output OCTETSTRING with encrypted content + encryptedContent = result; + // #endregion + + return crypto.exportKey("raw", sessionKey); + }, + function(error) + { + return Promise.reject(error); + } + ).then( + function(result) + { + exportedSessionKey = result; + + return true; + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Append common information to CMS_ENVELOPED_DATA + sequence = sequence.then( + function(result) + { + _this.version = 2; + _this.encryptedContentInfo = new in_window.org.pkijs.simpl.cms.EncryptedContentInfo({ + contentType: "1.2.840.113549.1.7.1", // "data" + contentEncryptionAlgorithm: new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: contentEncryptionOID, + algorithm_params: new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: ivBuffer }) + }), + encryptedContent: new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: encryptedContent }) + }); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + // #region Special sub-functions to work with each recipient's type + function KeyAgreeRecipientInfo(index) + { + // #region Initial variables + var currentSequence = Promise.resolve(); + + var ecdhPublicKey; + var ecdhPrivateKey; + + var recipientCurve; + var recipientCurveLength; + + var exportedECDHPublicKey; + // #endregion + + // #region Get "namedCurve" parameter from recipient's certificate + currentSequence = currentSequence.then( + function(result) + { + var curveObject = _this.recipientInfos[index].value.recipientCertificate.subjectPublicKeyInfo.algorithm.algorithm_params; + + if((curveObject instanceof in_window.org.pkijs.asn1.OID) === false) + return Promise.reject("Incorrect \"recipientCertificate\" for index " + index); + + var curveOID = curveObject.value_block.toString(); + + switch(curveOID) + { + case "1.2.840.10045.3.1.7": + recipientCurve = "P-256"; + recipientCurveLength = 256; + break; + case "1.3.132.0.34": + recipientCurve = "P-384"; + recipientCurveLength = 384; + break; + case "1.3.132.0.35": + recipientCurve = "P-521"; + recipientCurveLength = 528; + break; + default: + return Promise.reject("Incorrect curve OID for index " + index); + } + + return recipientCurve; + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Generate ephemeral ECDH key + currentSequence = currentSequence.then( + function(result) + { + return crypto.generateKey({ + name: "ECDH", + namedCurve: result + }, + true, + ["deriveBits"]); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Export public key of ephemeral ECDH key pair + currentSequence = currentSequence.then( + function(result) + { + ecdhPublicKey = result.publicKey; + ecdhPrivateKey = result.privateKey; + + return crypto.exportKey("spki", ecdhPublicKey); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Import recipient's public key + currentSequence = currentSequence.then( + function(result) + { + exportedECDHPublicKey = result; + + return _this.recipientInfos[index].value.recipientCertificate.getPublicKey({ + algorithm: { + algorithm: { + name: "ECDH", + namedCurve: recipientCurve + }, + usages: [] + } + }); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Create shared secret + currentSequence = currentSequence.then( + function(result) + { + return crypto.deriveBits({ + name: "ECDH", + public: result + }, + ecdhPrivateKey, + recipientCurveLength); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Apply KDF function to shared secret + currentSequence = currentSequence.then( + function(result) + { + // #region Get length of used AES-KW algorithm + var aesKWAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: _this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithm_params }); + + var KWalgorithm = in_window.org.pkijs.getAlgorithmByOID(aesKWAlgorithm.algorithm_id); + if(("name" in KWalgorithm) === false) + return Promise.reject("Incorrect OID for key encryption algorithm: " + aesKWAlgorithm.algorithm_id); + // #endregion + + // #region Translate AES-KW length to ArrayBuffer + var kwLength = KWalgorithm.length; + + var kwLengthBuffer = new ArrayBuffer(4); + var kwLengthView = new Uint8Array(kwLengthBuffer); + + for(var j = 3; j >= 0; j--) + { + kwLengthView[j] = kwLength; + kwLength >>= 8; + } + // #endregion + + // #region Create and encode "ECC-CMS-SharedInfo" structure + var eccInfo = new in_window.org.pkijs.simpl.cms.ECC_CMS_SharedInfo({ + keyInfo: new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: aesKWAlgorithm.algorithm_id, + /* + Initially RFC5753 says that AES algorithms have absent parameters. + But since early implementations all put NULL here. Thus, in order to be + "backward compatible", index also put NULL here. + */ + algorithm_params: new in_window.org.pkijs.asn1.NULL() + }), + entityUInfo: _this.recipientInfos[index].value.ukm, + suppPubInfo: new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: kwLengthBuffer }) + }); + + var encodedInfo = eccInfo.toSchema().toBER(false); + // #endregion + + // #region Get SHA algorithm used together with ECDH + var ecdhAlgorithm = in_window.org.pkijs.getAlgorithmByOID(_this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithm_id); + if(("name" in ecdhAlgorithm) === false) + return Promise.reject("Incorrect OID for key encryption algorithm: " + _this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithm_id); + // #endregion + + return in_window.org.pkijs.simpl.cms.kdf(ecdhAlgorithm.kdf, result, KWalgorithm.length, encodedInfo); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Import AES-KW key from result of KDF function + currentSequence = currentSequence.then( + function(result) + { + return crypto.importKey("raw", result, { name: "AES-KW" }, true, ["wrapKey"]); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Finally wrap session key by using AES-KW algorithm + currentSequence = currentSequence.then( + function(result) + { + return crypto.wrapKey("raw", sessionKey, result, { name: "AES-KW" }); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Append all neccessary data to current CMS_RECIPIENT_INFO object + currentSequence = currentSequence.then( + function(result) + { + // #region OriginatorIdentifierOrKey + var asn1 = org.pkijs.fromBER(exportedECDHPublicKey); + + var originator = new in_window.org.pkijs.simpl.cms.OriginatorIdentifierOrKey(); + originator.variant = 3; + originator.value = new in_window.org.pkijs.simpl.cms.OriginatorPublicKey({ schema: asn1.result }); + // There is option when we can stay with ECParameters, but here index prefer to avoid the params + if("algorithm_params" in originator.value.algorithm) + delete originator.value.algorithm.algorithm_params; + + _this.recipientInfos[index].value.originator = originator; + // #endregion + + // #region RecipientEncryptedKey + /* + We will not support using of same ephemeral key for many recipients + */ + _this.recipientInfos[index].value.recipientEncryptedKeys.encryptedKeys[0].encryptedKey = new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: result }); + // #endregion + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + return currentSequence; + } + + function KeyTransRecipientInfo(index) + { + // #region Initial variables + var currentSequence = Promise.resolve(); + // #endregion + + // #region Get recipient's public key + currentSequence = currentSequence.then( + function(result) + { + // #region Get current used SHA algorithm + var schema = _this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithm_params; + var rsaOAEPParams = new in_window.org.pkijs.simpl.cms.RSAES_OAEP_params({ schema: schema }); + + var hashAlgorithm = in_window.org.pkijs.getAlgorithmByOID(rsaOAEPParams.hashAlgorithm.algorithm_id); + if(("name" in hashAlgorithm) === false) + return Promise.reject("Incorrect OID for hash algorithm: " + rsaOAEPParams.hashAlgorithm.algorithm_id); + // #endregion + + return _this.recipientInfos[index].value.recipientCertificate.getPublicKey({ + algorithm: { + algorithm: { + name: "RSA-OAEP", + hash: { + name: hashAlgorithm.name + } + }, + usages: ["encrypt", "wrapKey"] + } + }); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Encrypt early exported session key on recipient's public key + currentSequence = currentSequence.then( + function(result) + { + return crypto.encrypt({ name: "RSA-OAEP" }, result, exportedSessionKey); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Append all neccessary data to current CMS_RECIPIENT_INFO object + currentSequence = currentSequence.then( + function(result) + { + // #region RecipientEncryptedKey + _this.recipientInfos[index].value.encryptedKey = new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: result }); + // #endregion + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + return currentSequence; + } + + function KEKRecipientInfo(index) + { + // #region Initial variables + var currentSequence = Promise.resolve(); + var kekAlgorithm; + // #endregion + + // #region Import KEK from pre-defined data + currentSequence = currentSequence.then( + function(result) + { + // #region Get WebCrypto form of "keyEncryptionAlgorithm" + kekAlgorithm = in_window.org.pkijs.getAlgorithmByOID(_this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithm_id); + if(("name" in kekAlgorithm) === false) + return Promise.reject("Incorrect OID for \"keyEncryptionAlgorithm\": " + _this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithm_id); + // #endregion + + return crypto.importKey("raw", + new Uint8Array(_this.recipientInfos[index].value.preDefinedKEK), + kekAlgorithm, + true, + ['wrapKey']); // Too specific for AES-KW + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Wrap previously exported session key + currentSequence = currentSequence.then( + function(result) + { + + return crypto.wrapKey("raw", sessionKey, result, kekAlgorithm); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Append all neccessary data to current CMS_RECIPIENT_INFO object + currentSequence = currentSequence.then( + function(result) + { + // #region RecipientEncryptedKey + _this.recipientInfos[index].value.encryptedKey = new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: result }); + // #endregion + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + return currentSequence; + } + + function PasswordRecipientinfo(index) + { + // #region Initial variables + var currentSequence = Promise.resolve(); + var pbkdf2Params; + var kekAlgorithm; + // #endregion + + // #region Check that we have encoded "keyDerivationAlgorithm" plus "PBKDF2_params" in there + currentSequence = currentSequence.then( + function(result) + { + if(("keyDerivationAlgorithm" in _this.recipientInfos[index].value) === false) + return Promise.reject("Please append encoded \"keyDerivationAlgorithm\""); + + if(("algorithm_params" in _this.recipientInfos[index].value.keyDerivationAlgorithm) === false) + return Promise.reject("Incorrectly encoded \"keyDerivationAlgorithm\""); + + try + { + pbkdf2Params = new in_window.org.pkijs.simpl.cms.PBKDF2_params({ schema: _this.recipientInfos[index].value.keyDerivationAlgorithm.algorithm_params }); + } + catch(ex) + { + return Promise.reject("Incorrectly encoded \"keyDerivationAlgorithm\""); + } + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Derive PBKDF2 key from "password" buffer + currentSequence = currentSequence.then( + function(result) + { + var passwordView = new Uint8Array(_this.recipientInfos[index].value.password); + + return crypto.importKey("raw", + passwordView, + "PBKDF2", + true, + ['deriveKey']); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Derive key for "keyEncryptionAlgorithm" + currentSequence = currentSequence.then( + function(result) + { + // #region Get WebCrypto form of "keyEncryptionAlgorithm" + kekAlgorithm = in_window.org.pkijs.getAlgorithmByOID(_this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithm_id); + if(("name" in kekAlgorithm) === false) + return Promise.reject("Incorrect OID for \"keyEncryptionAlgorithm\": " + _this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithm_id); + // #endregion + + // #region Get HMAC hash algorithm + var hmacHashAlgorithm = "SHA-1"; + + if("prf" in pbkdf2Params) + { + var algorithm = in_window.org.pkijs.getAlgorithmByOID(pbkdf2Params.prf.algorithm_id); + if(("name" in algorithm) === false) + return Promise.reject("Incorrect OID for HMAC hash algorithm"); + + hmacHashAlgorithm = algorithm.hash.name; + } + // #endregion + + // #region Get PBKDF2 "salt" value + var saltView = new Uint8Array(pbkdf2Params.salt.value_block.value_hex); + // #endregion + + // #region Get PBKDF2 iterations count + var iterations = pbkdf2Params.iterationCount; + // #endregion + + return crypto.deriveKey({ + name: "PBKDF2", + hash: { + name: hmacHashAlgorithm + }, + salt: saltView, + iterations: iterations + }, + result, + kekAlgorithm, + true, + ['wrapKey']); // Usages are too specific for KEK algorithm + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Wrap previously exported session key + currentSequence = currentSequence.then( + function(result) + { + /* + Also too specific for KEK algorithm. + */ + return crypto.wrapKey("raw", sessionKey, result, kekAlgorithm); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Append all neccessary data to current CMS_RECIPIENT_INFO object + currentSequence = currentSequence.then( + function(result) + { + // #region RecipientEncryptedKey + _this.recipientInfos[index].value.encryptedKey = new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: result }); + // #endregion + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + return currentSequence; + } + // #endregion + + // #region Create special routines for each "recipient" + sequence = sequence.then( + function(result) + { + for(var i = 0; i < _this.recipientInfos.length; i++) + { + // #region Initial variables + var currentSequence = Promise.resolve(); + // #endregion + + switch(_this.recipientInfos[i].variant) + { + case 1: // KeyTransRecipientInfo + currentSequence = KeyTransRecipientInfo(i); + break; + case 2: // KeyAgreeRecipientInfo + currentSequence = KeyAgreeRecipientInfo(i); + break; + case 3: // KEKRecipientInfo + currentSequence = KEKRecipientInfo(i); + break; + case 4: // PasswordRecipientinfo + currentSequence = PasswordRecipientinfo(i); + break; + default: + return Promise.reject("Uknown recipient type in array with index " + i); + } + + recipientsPromises.push(currentSequence); + } + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + // #region Run separate thread for each recipient + sequence = sequence.then( + function(result) + { + return Promise.all(recipientsPromises); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + return sequence; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_ENVELOPED_DATA.prototype.decrypt = + function(recipientIndex, parameters) + { + /// Decrypt existing CMS Enveloped Data content + /// Index of recipient + /// Additional parameters + + // #region Initial variables + var _this = this; + var sequence = Promise.resolve(); + + var decryptionParameters = parameters || {}; + // #endregion + + // #region Check for input parameters + if((recipientIndex + 1) > this.recipientInfos.length) + return Promise.reject("Maximum value for \"index\" is: " + (_this.recipientInfos.length - 1)); + // #endregion + + // #region Get a "crypto" extension + var crypto = in_window.org.pkijs.getCrypto(); + if(typeof crypto == "undefined") + return Promise.reject("Unable to create WebCrypto object"); + // #endregion + + // #region Special sub-functions to work with each recipient's type + function KeyAgreeRecipientInfo(index) + { + // #region Initial variables + var currentSequence = Promise.resolve(); + + var recipientCurve; + var recipientCurveLength; + + var curveOID; + + var ecdhPrivateKey; + // #endregion + + // #region Get "namedCurve" parameter from recipient's certificate + currentSequence = currentSequence.then( + function(result) + { + if(("recipientCertificate" in decryptionParameters) === false) + return Promise.reject("Parameter \"recipientCertificate\" is mandatory for \"KeyAgreeRecipientInfo\""); + + if(("recipientPrivateKey" in decryptionParameters) === false) + return Promise.reject("Parameter \"recipientPrivateKey\" is mandatory for \"KeyAgreeRecipientInfo\""); + + var curveObject = decryptionParameters.recipientCertificate.subjectPublicKeyInfo.algorithm.algorithm_params; + + if((curveObject instanceof in_window.org.pkijs.asn1.OID) === false) + return Promise.reject("Incorrect \"recipientCertificate\" for index " + index); + + curveOID = curveObject.value_block.toString(); + + switch(curveOID) + { + case "1.2.840.10045.3.1.7": + recipientCurve = "P-256"; + recipientCurveLength = 256; + break; + case "1.3.132.0.34": + recipientCurve = "P-384"; + recipientCurveLength = 384; + break; + case "1.3.132.0.35": + recipientCurve = "P-521"; + recipientCurveLength = 528; + break; + default: + return Promise.reject("Incorrect curve OID for index " + index); + } + + return crypto.importKey("pkcs8", + decryptionParameters.recipientPrivateKey, + { + name: "ECDH", + namedCurve: recipientCurve + }, + true, + ["deriveBits"] + ); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Import sender's ephemeral public key + currentSequence = currentSequence.then( + function(result) + { + ecdhPrivateKey = result; + + // #region Change "OriginatorPublicKey" if "curve" parameter absent + if(("algorithm_params" in _this.recipientInfos[index].value.originator.value.algorithm) === false) + _this.recipientInfos[index].value.originator.value.algorithm.algorithm_params = new in_window.org.pkijs.asn1.OID({ value: curveOID }); + // #endregion + + // #region Create ArrayBuffer with sender's public key + var buffer = _this.recipientInfos[index].value.originator.value.toSchema().toBER(false); + // #endregion + + return crypto.importKey("spki", + buffer, + { + name: "ECDH", + namedCurve: recipientCurve + }, + true, + []); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Create shared secret + currentSequence = currentSequence.then( + function(result) + { + return crypto.deriveBits({ + name: "ECDH", + public: result + }, + ecdhPrivateKey, + recipientCurveLength); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Apply KDF function to shared secret + currentSequence = currentSequence.then( + function(result) + { + // #region Get length of used AES-KW algorithm + var aesKWAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: _this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithm_params }); + + var KWalgorithm = in_window.org.pkijs.getAlgorithmByOID(aesKWAlgorithm.algorithm_id); + if(("name" in KWalgorithm) === false) + return Promise.reject("Incorrect OID for key encryption algorithm: " + aesKWAlgorithm.algorithm_id); + // #endregion + + // #region Translate AES-KW length to ArrayBuffer + var kwLength = KWalgorithm.length; + + var kwLengthBuffer = new ArrayBuffer(4); + var kwLengthView = new Uint8Array(kwLengthBuffer); + + for(var j = 3; j >= 0; j--) + { + kwLengthView[j] = kwLength; + kwLength >>= 8; + } + // #endregion + + // #region Create and encode "ECC-CMS-SharedInfo" structure + var eccInfo = new in_window.org.pkijs.simpl.cms.ECC_CMS_SharedInfo({ + keyInfo: new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: aesKWAlgorithm.algorithm_id, + /* + Initially RFC5753 says that AES algorithms have absent parameters. + But since early implementations all put NULL here. Thus, in order to be + "backward compatible", index also put NULL here. + */ + algorithm_params: new in_window.org.pkijs.asn1.NULL() + }), + entityUInfo: _this.recipientInfos[index].value.ukm, + suppPubInfo: new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: kwLengthBuffer }) + }); + + var encodedInfo = eccInfo.toSchema().toBER(false); + // #endregion + + // #region Get SHA algorithm used together with ECDH + var ecdhAlgorithm = in_window.org.pkijs.getAlgorithmByOID(_this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithm_id); + if(("name" in ecdhAlgorithm) === false) + return Promise.reject("Incorrect OID for key encryption algorithm: " + _this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithm_id); + // #endregion + + return in_window.org.pkijs.simpl.cms.kdf(ecdhAlgorithm.kdf, result, KWalgorithm.length, encodedInfo); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Import AES-KW key from result of KDF function + currentSequence = currentSequence.then( + function(result) + { + return crypto.importKey("raw", + result, + { name: "AES-KW" }, + true, + ["unwrapKey"]); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Finally unwrap session key + currentSequence = currentSequence.then( + function(result) + { + // #region Get WebCrypto form of content encryption algorithm + var contentEncryptionAlgorithm = in_window.org.pkijs.getAlgorithmByOID(_this.encryptedContentInfo.contentEncryptionAlgorithm.algorithm_id); + if(("name" in contentEncryptionAlgorithm) === false) + return Promise.reject("Incorrect \"contentEncryptionAlgorithm\": " + _this.encryptedContentInfo.contentEncryptionAlgorithm.algorithm_id); + // #endregion + + return crypto.unwrapKey("raw", + _this.recipientInfos[index].value.recipientEncryptedKeys.encryptedKeys[0].encryptedKey.value_block.value_hex, + result, + { name: "AES-KW" }, + contentEncryptionAlgorithm, + true, + ["decrypt"]); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + return currentSequence; + } + + function KeyTransRecipientInfo(index) + { + // #region Initial variables + var currentSequence = Promise.resolve(); + // #endregion + + // #region Import recipient's private key + currentSequence = currentSequence.then( + function(result) + { + if(("recipientPrivateKey" in decryptionParameters) === false) + return Promise.reject("Parameter \"recipientPrivateKey\" is mandatory for \"KeyTransRecipientInfo\""); + + // #region Get current used SHA algorithm + var schema = _this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithm_params; + var rsaOAEPParams = new in_window.org.pkijs.simpl.cms.RSAES_OAEP_params({ schema: schema }); + + var hashAlgorithm = in_window.org.pkijs.getAlgorithmByOID(rsaOAEPParams.hashAlgorithm.algorithm_id); + if(("name" in hashAlgorithm) === false) + return Promise.reject("Incorrect OID for hash algorithm: " + rsaOAEPParams.hashAlgorithm.algorithm_id); + // #endregion + + return crypto.importKey("pkcs8", + decryptionParameters.recipientPrivateKey, + { + name: "RSA-OAEP", + hash: { + name: hashAlgorithm.name + } + }, + true, + ["decrypt"]); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Decrypt encrypted session key + currentSequence = currentSequence.then( + function(result) + { + return crypto.decrypt({ + name: "RSA-OAEP" + }, + result, + _this.recipientInfos[index].value.encryptedKey.value_block.value_hex + ); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Import decrypted session key + currentSequence = currentSequence.then( + function(result) + { + // #region Get WebCrypto form of content encryption algorithm + var contentEncryptionAlgorithm = in_window.org.pkijs.getAlgorithmByOID(_this.encryptedContentInfo.contentEncryptionAlgorithm.algorithm_id); + if(("name" in contentEncryptionAlgorithm) === false) + return Promise.reject("Incorrect \"contentEncryptionAlgorithm\": " + _this.encryptedContentInfo.contentEncryptionAlgorithm.algorithm_id); + // #endregion + + return crypto.importKey("raw", + result, + contentEncryptionAlgorithm, + true, + ["decrypt"] + ); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + return currentSequence; + } + + function KEKRecipientInfo(index) + { + // #region Initial variables + var currentSequence = Promise.resolve(); + var kekAlgorithm; + // #endregion + + // #region Import KEK from pre-defined data + currentSequence = currentSequence.then( + function(result) + { + if(("preDefinedData" in decryptionParameters) === false) + return Promise.reject("Parameter \"preDefinedData\" is mandatory for \"KEKRecipientInfo\""); + + // #region Get WebCrypto form of "keyEncryptionAlgorithm" + kekAlgorithm = in_window.org.pkijs.getAlgorithmByOID(_this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithm_id); + if(("name" in kekAlgorithm) === false) + return Promise.reject("Incorrect OID for \"keyEncryptionAlgorithm\": " + _this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithm_id); + // #endregion + + return crypto.importKey("raw", + decryptionParameters.preDefinedData, + kekAlgorithm, + true, + ["unwrapKey"]); // Too specific for AES-KW + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Unwrap previously exported session key + currentSequence = currentSequence.then( + function(result) + { + // #region Get WebCrypto form of content encryption algorithm + var contentEncryptionAlgorithm = in_window.org.pkijs.getAlgorithmByOID(_this.encryptedContentInfo.contentEncryptionAlgorithm.algorithm_id); + if(("name" in contentEncryptionAlgorithm) === false) + return Promise.reject("Incorrect \"contentEncryptionAlgorithm\": " + _this.encryptedContentInfo.contentEncryptionAlgorithm.algorithm_id); + // #endregion + + return crypto.unwrapKey("raw", + _this.recipientInfos[index].value.encryptedKey.value_block.value_hex, + result, + kekAlgorithm, + contentEncryptionAlgorithm, + true, + ["decrypt"]); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + return currentSequence; + } + + function PasswordRecipientinfo(index) + { + // #region Initial variables + var currentSequence = Promise.resolve(); + var pbkdf2Params; + var kekAlgorithm; + // #endregion + + // #region Derive PBKDF2 key from "password" buffer + currentSequence = currentSequence.then( + function(result) + { + if(("preDefinedData" in decryptionParameters) === false) + return Promise.reject("Parameter \"preDefinedData\" is mandatory for \"KEKRecipientInfo\""); + + if(("keyDerivationAlgorithm" in _this.recipientInfos[index].value) === false) + return Promise.reject("Please append encoded \"keyDerivationAlgorithm\""); + + if(("algorithm_params" in _this.recipientInfos[index].value.keyDerivationAlgorithm) === false) + return Promise.reject("Incorrectly encoded \"keyDerivationAlgorithm\""); + + try + { + pbkdf2Params = new in_window.org.pkijs.simpl.cms.PBKDF2_params({ schema: _this.recipientInfos[index].value.keyDerivationAlgorithm.algorithm_params }); + } + catch(ex) + { + return Promise.reject("Incorrectly encoded \"keyDerivationAlgorithm\""); + } + + return crypto.importKey("raw", + decryptionParameters.preDefinedData, + "PBKDF2", + true, + ["deriveKey"]); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Derive key for "keyEncryptionAlgorithm" + currentSequence = currentSequence.then( + function(result) + { + // #region Get WebCrypto form of "keyEncryptionAlgorithm" + kekAlgorithm = in_window.org.pkijs.getAlgorithmByOID(_this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithm_id); + if(("name" in kekAlgorithm) === false) + return Promise.reject("Incorrect OID for \"keyEncryptionAlgorithm\": " + _this.recipientInfos[index].value.keyEncryptionAlgorithm.algorithm_id); + // #endregion + + // #region Get HMAC hash algorithm + var hmacHashAlgorithm = "SHA-1"; + + if("prf" in pbkdf2Params) + { + var algorithm = in_window.org.pkijs.getAlgorithmByOID(pbkdf2Params.prf.algorithm_id); + if(("name" in algorithm) === false) + return Promise.reject("Incorrect OID for HMAC hash algorithm"); + + hmacHashAlgorithm = algorithm.hash.name; + } + // #endregion + + // #region Get PBKDF2 "salt" value + var saltView = new Uint8Array(pbkdf2Params.salt.value_block.value_hex); + // #endregion + + // #region Get PBKDF2 iterations count + var iterations = pbkdf2Params.iterationCount; + // #endregion + + return crypto.deriveKey({ + name: "PBKDF2", + hash: { + name: hmacHashAlgorithm + }, + salt: saltView, + iterations: iterations + }, + result, + kekAlgorithm, + true, + ['unwrapKey']); // Usages are too specific for KEK algorithm + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #region Unwrap previously exported session key + currentSequence = currentSequence.then( + function(result) + { + // #region Get WebCrypto form of content encryption algorithm + var contentEncryptionAlgorithm = in_window.org.pkijs.getAlgorithmByOID(_this.encryptedContentInfo.contentEncryptionAlgorithm.algorithm_id); + if(("name" in contentEncryptionAlgorithm) === false) + return Promise.reject("Incorrect \"contentEncryptionAlgorithm\": " + _this.encryptedContentInfo.contentEncryptionAlgorithm.algorithm_id); + // #endregion + + return crypto.unwrapKey("raw", + _this.recipientInfos[index].value.encryptedKey.value_block.value_hex, + result, + kekAlgorithm, + contentEncryptionAlgorithm, + true, + ["decrypt"]); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + return currentSequence; + } + // #endregion + + // #region Perform steps, specific to each type of session key encryption + sequence = sequence.then( + function(result) + { + // #region Initial variables + var currentSequence = Promise.resolve(); + // #endregion + + switch(_this.recipientInfos[recipientIndex].variant) + { + case 1: // KeyTransRecipientInfo + currentSequence = KeyTransRecipientInfo(recipientIndex); + break; + case 2: // KeyAgreeRecipientInfo + currentSequence = KeyAgreeRecipientInfo(recipientIndex); + break; + case 3: // KEKRecipientInfo + currentSequence = KEKRecipientInfo(recipientIndex); + break; + case 4: // PasswordRecipientinfo + currentSequence = PasswordRecipientinfo(recipientIndex); + break; + default: + return Promise.reject("Uknown recipient type in array with index " + recipientIndex); + } + + return currentSequence; + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + // #region Finally decrypt data by session key + sequence = sequence.then( + function(result) + { + // #region Get WebCrypto form of content encryption algorithm + var contentEncryptionAlgorithm = in_window.org.pkijs.getAlgorithmByOID(_this.encryptedContentInfo.contentEncryptionAlgorithm.algorithm_id); + if(("name" in contentEncryptionAlgorithm) === false) + return Promise.reject("Incorrect \"contentEncryptionAlgorithm\": " + _this.encryptedContentInfo.contentEncryptionAlgorithm.algorithm_id); + // #endregion + + // #region Get "intialization vector" for content encryption algorithm + var ivBuffer = _this.encryptedContentInfo.contentEncryptionAlgorithm.algorithm_params.value_block.value_hex; + var ivView = new Uint8Array(ivBuffer); + // #endregion + + // #region Create correct data block for decryption + var dataBuffer = new ArrayBuffer(0); + + if(_this.encryptedContentInfo.encryptedContent.id_block.is_constructed === false) + dataBuffer = _this.encryptedContentInfo.encryptedContent.value_block.value_hex; + else + { + for(var i = 0; i < _this.encryptedContentInfo.encryptedContent.value_block.value.length; i++) + dataBuffer = in_window.org.pkijs.concat_buffers(dataBuffer, _this.encryptedContentInfo.encryptedContent.value_block.value[i].value_block.value_hex); + } + // #endregion + + return crypto.decrypt({ + name: contentEncryptionAlgorithm.name, + iv: ivView + }, + result, + dataBuffer); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + return sequence; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "CMS_ENCRYPTED_DATA" type + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_ENCRYPTED_DATA = + function() + { + // #region Internal properties of the object + this.version = 0; + this.encryptedContentInfo = new in_window.org.pkijs.simpl.cms.EncryptedContentInfo(); + // OPTIONAL this.unprotectedAttrs + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.CMS_ENCRYPTED_DATA.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.version = arguments[0].version || 0; + this.encryptedContentInfo = arguments[0].encryptedContentInfo || new in_window.org.pkijs.simpl.cms.EncryptedContentInfo(); + + if("unprotectedAttrs" in arguments[0]) + { + this.unprotectedAttrs = arguments[0].unprotectedAttrs; + this.version = 2; + } + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_ENCRYPTED_DATA.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.CMS_ENCRYPTED_DATA({ + names: { + version: "version", + encryptedContentInfo: { + names: { + block_name: "encryptedContentInfo" + } + }, + unprotectedAttrs: "unprotectedAttrs" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for CMS_ENCRYPTED_DATA"); + // #endregion + + // #region Get internal properties from parsed schema + this.version = asn1.result["version"].value_block.value_dec; + this.encryptedContentInfo = new in_window.org.pkijs.simpl.cms.EncryptedContentInfo({ schema: asn1.result["encryptedContentInfo"] }); + + if("unprotectedAttrs" in asn1.result) + { + this.unprotectedAttrs = new Array(); + var attributes_array = asn1.result["unprotectedAttrs"]; + + for(var j = 0; j < attributes_array.length; j++) + this.unprotectedAttrs.push(new in_window.org.pkijs.simpl.ATTRIBUTE({ schema: attributes_array[j] })); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_ENCRYPTED_DATA.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + output_array.push(new in_window.org.pkijs.asn1.INTEGER({ value: this.version })); + output_array.push(this.encryptedContentInfo.toSchema()); + + if("unprotectedAttrs" in this) + { + var attributes = new Array(); + + for(var j = 0; j < this.unprotectedAttrs.length; j++) + attributes.push(this.unprotectedAttrs[j].toSchema()); + + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: attributes + })); + } + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_ENCRYPTED_DATA.prototype.toJSON = + function() + { + var _object = { + version: this.version + }; + + _object.encryptedContentInfo = this.encryptedContentInfo.toJSON(); + + if("unprotectedAttrs" in this) + { + _object.unprotectedAttrs = new Array(); + + for(var i = 0; i < this.unprotectedAttrs.length; i++) + _object.unprotectedAttrs.push(this.unprotectedAttrs[i].toJSON()); + } + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_ENCRYPTED_DATA.prototype.encrypt = + function(parameters) + { + /// Create a new CMS Encrypted Data content + /// Parameters neccessary for encryption + + // #region Check for input parameters + if((parameters instanceof Object) == false) + return Promise.reject("Parameters must have type \"Object\""); + + if(("password" in parameters) == false) + return Promise.reject("Absent mandatory parameter \"password\""); + + if(("contentEncryptionAlgorithm" in parameters) == false) + return Promise.reject("Absent mandatory parameter \"contentEncryptionAlgorithm\""); + + if(("hmacHashAlgorithm" in parameters) == false) + return Promise.reject("Absent mandatory parameter \"hmacHashAlgorithm\""); + + if(("iterationCount" in parameters) == false) + return Promise.reject("Absent mandatory parameter \"iterationCount\""); + + if(("contentToEncrypt" in parameters) == false) + return Promise.reject("Absent mandatory parameter \"contentToEncrypt\""); + + var contentEncryptionOID = in_window.org.pkijs.getOIDByAlgorithm(parameters.contentEncryptionAlgorithm); + if(contentEncryptionOID === "") + return Promise.reject("Wrong \"contentEncryptionAlgorithm\" value"); + + var pbkdf2OID = in_window.org.pkijs.getOIDByAlgorithm({ + name: "PBKDF2" + }); + if(pbkdf2OID === "") + return Promise.reject("Can not find OID for PBKDF2"); + + var hmacOID = in_window.org.pkijs.getOIDByAlgorithm({ + name: "HMAC", + hash: { + name: parameters.hmacHashAlgorithm + } + }); + if(hmacOID === "") + return Promise.reject("Incorrect value for \"hmacHashAlgorithm\": " + parameters.hmacHashAlgorithm); + // #endregion + + // #region Get a "crypto" extension + var crypto = in_window.org.pkijs.getCrypto(); + if(typeof crypto == "undefined") + return Promise.reject("Unable to create WebCrypto object"); + // #endregion + + // #region Initial variables + var _this = this; + var sequence = Promise.resolve(); + + var ivBuffer = new ArrayBuffer(16); // For AES we need IV 16 bytes long + var ivView = new Uint8Array(ivBuffer); + in_window.org.pkijs.getRandomValues(ivView); + + var saltBuffer = new ArrayBuffer(64); + var saltView = new Uint8Array(saltBuffer); + in_window.org.pkijs.getRandomValues(saltView); + + var contentView = new Uint8Array(parameters.contentToEncrypt); + + var pbkdf2Params = new in_window.org.pkijs.simpl.cms.PBKDF2_params({ + salt: new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: saltBuffer }), + iterationCount: parameters.iterationCount, + prf: new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: hmacOID, + algorithm_params: new in_window.org.pkijs.asn1.NULL() + }) + }); + // #endregion + + // #region Derive PBKDF2 key from "password" buffer + sequence = sequence.then( + function(result) + { + var passwordView = new Uint8Array(parameters.password); + + return crypto.importKey("raw", + passwordView, + "PBKDF2", + true, + ['deriveKey']); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + // #region Derive key for "contentEncryptionAlgorithm" + sequence = sequence.then( + function(result) + { + return crypto.deriveKey({ + name: "PBKDF2", + hash: { + name: parameters.hmacHashAlgorithm + }, + salt: saltView, + iterations: parameters.iterationCount + }, + result, + parameters.contentEncryptionAlgorithm, + true, + ['encrypt']); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + // #region Encrypt content + sequence = sequence.then( + function(result) + { + return crypto.encrypt({ + name: parameters.contentEncryptionAlgorithm.name, + iv: ivView + }, + result, + contentView); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + // #region Store all parameters in CMS_ENCRYPTED_DATA + sequence = sequence.then( + function(result) + { + var pbes2Parameters = new in_window.org.pkijs.simpl.cms.PBES2_params({ + keyDerivationFunc: new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: pbkdf2OID, + algorithm_params: pbkdf2Params.toSchema() + }), + encryptionScheme: new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: contentEncryptionOID, + algorithm_params: new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: ivBuffer }) + }) + }); + + _this.encryptedContentInfo = new in_window.org.pkijs.simpl.cms.EncryptedContentInfo({ + contentType: "1.2.840.113549.1.7.1", // "data" + contentEncryptionAlgorithm: new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: "1.2.840.113549.1.5.13", // pkcs5PBES2 + algorithm_params: pbes2Parameters.toSchema() + }), + encryptedContent: new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: result }) + }); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + return sequence; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CMS_ENCRYPTED_DATA.prototype.decrypt = + function(parameters) + { + /// Create a new CMS Encrypted Data content + /// Parameters neccessary for encryption + + // #region Check for input parameters + if((parameters instanceof Object) == false) + return Promise.reject("Parameters must have type \"Object\""); + + if(("password" in parameters) == false) + return Promise.reject("Absent mandatory parameter \"password\""); + + if(this.encryptedContentInfo.contentEncryptionAlgorithm.algorithm_id !== "1.2.840.113549.1.5.13") // pkcs5PBES2 + return Promise.reject("Unknown \"contentEncryptionAlgorithm\": " + _this.encryptedContentInfo.contentEncryptionAlgorithm.algorithm_id); + // #endregion + + // #region Get a "crypto" extension + var crypto = in_window.org.pkijs.getCrypto(); + if(typeof crypto == "undefined") + return Promise.reject("Unable to create WebCrypto object"); + // #endregion + + // #region Initial variables + var _this = this; + var sequence = Promise.resolve(); + + var pbes2Parameters; + + try + { + pbes2Parameters = new in_window.org.pkijs.simpl.cms.PBES2_params({ schema: _this.encryptedContentInfo.contentEncryptionAlgorithm.algorithm_params }); + } + catch(ex) + { + return Promise.reject("Incorrectly encoded \"pbes2Parameters\""); + } + + var pbkdf2Params; + + try + { + pbkdf2Params = new in_window.org.pkijs.simpl.cms.PBKDF2_params({ schema: pbes2Parameters.keyDerivationFunc.algorithm_params }); + } + catch(ex) + { + return Promise.reject("Incorrectly encoded \"pbkdf2Params\""); + } + + var contentEncryptionAlgorithm = in_window.org.pkijs.getAlgorithmByOID(pbes2Parameters.encryptionScheme.algorithm_id); + if(("name" in contentEncryptionAlgorithm) == false) + return Promise.reject("Incorrect OID for \"contentEncryptionAlgorithm\": " + pbes2Parameters.encryptionScheme.algorithm_id); + + var ivBuffer = pbes2Parameters.encryptionScheme.algorithm_params.value_block.value_hex; + var ivView = new Uint8Array(ivBuffer); + + var saltBuffer = pbkdf2Params.salt.value_block.value_hex; + var saltView = new Uint8Array(saltBuffer); + + var iterationCount = pbkdf2Params.iterationCount; + + var hmacHashAlgorithm = "SHA-1"; + + if("prf" in pbkdf2Params) + { + var algorithm = in_window.org.pkijs.getAlgorithmByOID(pbkdf2Params.prf.algorithm_id); + if(("name" in algorithm) === false) + return Promise.reject("Incorrect OID for HMAC hash algorithm"); + + hmacHashAlgorithm = algorithm.hash.name; + } + // #endregion + + // #region Derive PBKDF2 key from "password" buffer + sequence = sequence.then( + function(result) + { + return crypto.importKey("raw", + parameters.password, + "PBKDF2", + true, + ["deriveKey"]); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + // #region Derive key for "contentEncryptionAlgorithm" + sequence = sequence.then( + function(result) + { + return crypto.deriveKey({ + name: "PBKDF2", + hash: { + name: hmacHashAlgorithm + }, + salt: saltView, + iterations: iterationCount + }, + result, + contentEncryptionAlgorithm, + true, + ['decrypt']); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + // #region Decrypt internal content using derived key + sequence = sequence.then( + function(result) + { + // #region Create correct data block for decryption + var dataBuffer = new ArrayBuffer(0); + + if(_this.encryptedContentInfo.encryptedContent.id_block.is_constructed === false) + dataBuffer = _this.encryptedContentInfo.encryptedContent.value_block.value_hex; + else + { + for(var i = 0; i < _this.encryptedContentInfo.encryptedContent.value_block.value.length; i++) + dataBuffer = in_window.org.pkijs.concat_buffers(dataBuffer, _this.encryptedContentInfo.encryptedContent.value_block.value[i].value_block.value_hex); + } + // #endregion + + return crypto.decrypt({ + name: contentEncryptionAlgorithm.name, + iv: ivView + }, + result, + dataBuffer); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + return sequence; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** +} +)(typeof exports !== "undefined" ? exports : window); \ No newline at end of file diff --git a/express-server/node_modules/pkijs/org/pkijs/common.js b/express-server/node_modules/pkijs/org/pkijs/common.js new file mode 100644 index 00000000..4fd8f37c --- /dev/null +++ b/express-server/node_modules/pkijs/org/pkijs/common.js @@ -0,0 +1,1559 @@ +/* + * Copyright (c) 2014, GMO GlobalSign + * Copyright (c) 2015, Peculiar Ventures + * All rights reserved. + * + * Author 2014-2015, Yury Strozhevsky . + * + * 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 copyright holder 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. + * + */ +( +function(in_window) +{ + //************************************************************************************** + // #region Declaration of global variables + //************************************************************************************** + // #region "org" namespace + if(typeof in_window.org === "undefined") + in_window.org = {}; + else + { + if(typeof in_window.org !== "object") + throw new Error("Name org already exists and it's not an object"); + } + // #endregion + + // #region "org.pkijs" namespace + if(typeof in_window.org.pkijs === "undefined") + in_window.org.pkijs = {}; + else + { + if(typeof in_window.org.pkijs !== "object") + throw new Error("Name org.pkijs already exists and it's not an object" + " but " + (typeof in_window.org.pkijs)); + } + // #endregion + + // #region "local" namespace + var local = {}; + // #endregion + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Settings for "crypto engine" + //************************************************************************************** + local.engine = { + name: "none", + crypto: null, + subtle: null + }; + + if(typeof window != "undefined") + { + if("crypto" in window) + { + var engineName = "webcrypto"; + var cryptoObject = window.crypto; + var subtleObject = null; + + // Apple Safari support + if("webkitSubtle" in window.crypto) + subtleObject = window.crypto.webkitSubtle; + + if("subtle" in window.crypto) + subtleObject = window.crypto.subtle; + + local.engine = { + name: engineName, + crypto: cryptoObject, + subtle: subtleObject + }; + } + } + //************************************************************************************** + in_window.org.pkijs.setEngine = + function(name, crypto, subtle) + { + /// Setting the global "crypto engine" parameters + /// Auxiliary name for "crypto engine" + /// Object handling all root cryptographic requests (in fact currently it must handle only "getRandomValues") + /// Object handling all main cryptographic requests + + local.engine = { + name: name, + crypto: crypto, + subtle: subtle + }; + }; + //************************************************************************************** + in_window.org.pkijs.getEngine = + function() + { + return local.engine; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Declaration of common functions + //************************************************************************************** + in_window.org.pkijs.emptyObject = + function() + { + this.toJSON = function() + { + return {}; + }; + this.toSchema = function() + { + return {}; + }; + }; + //************************************************************************************** + in_window.org.pkijs.getNames = + function(arg) + { + /// Get correct "names" array for all "schema" objects + + var names = {}; + + if(arg instanceof Object) + names = (arg.names || {}); + + return names; + }; + //************************************************************************************** + in_window.org.pkijs.inheriteObjectFields = + function(from) + { + for(var i in from.prototype) + { + if(typeof from.prototype[i] === "function") + continue; + + this[i] = from.prototype[i]; + } + }; + //************************************************************************************** + in_window.org.pkijs.getUTCDate = + function(date) + { + /// Making UTC date from local date + /// Date to convert from + + var current_date = date; + return new Date(current_date.getTime() + (current_date.getTimezoneOffset() * 60000)); + }; + //************************************************************************************** + in_window.org.pkijs.padNumber = + function(input_number, full_length) + { + var str = input_number.toString(10); + var dif = full_length - str.length; + + var padding = new Array(dif); + for(var i = 0; i < dif; i++) + padding[i] = '0'; + + var padding_string = padding.join(''); + + return padding_string.concat(str); + }; + //************************************************************************************** + in_window.org.pkijs.getValue = + function(args, item, default_value) + { + if(item in args) + return args[item]; + else + return default_value; + }; + //************************************************************************************** + in_window.org.pkijs.isEqual_view = + function(input_view1, input_view2) + { + /// Compare two Uint8Arrays + /// First Uint8Array for comparision + /// Second Uint8Array for comparision + + if(input_view1.length !== input_view2.length) + return false; + + for(var i = 0; i < input_view1.length; i++) + { + if(input_view1[i] != input_view2[i]) + return false; + } + + return true; + }; + //************************************************************************************** + in_window.org.pkijs.isEqual_buffer = + function(input_buffer1, input_buffer2) + { + /// Compare two array buffers + /// First ArrayBuffer for comparision + /// Second ArrayBuffer for comparision + + if(input_buffer1.byteLength != input_buffer2.byteLength) + return false; + + var view1 = new Uint8Array(input_buffer1); + var view2 = new Uint8Array(input_buffer2); + + return in_window.org.pkijs.isEqual_view(view1, view2); + }; + //************************************************************************************** + in_window.org.pkijs.concat_buffers = + function(input_buf1, input_buf2) + { + /// Concatenate two ArrayBuffers + /// First ArrayBuffer (first part of concatenated array) + /// Second ArrayBuffer (second part of concatenated array) + + var input_view1 = new Uint8Array(input_buf1); + var input_view2 = new Uint8Array(input_buf2); + + var ret_buf = new ArrayBuffer(input_buf1.byteLength + input_buf2.byteLength); + var ret_view = new Uint8Array(ret_buf); + + for(var i = 0; i < input_buf1.byteLength; i++) + ret_view[i] = input_view1[i]; + + for(var j = 0; j < input_buf2.byteLength; j++) + ret_view[input_buf1.byteLength + j] = input_view2[j]; + + return ret_buf; + }; + //************************************************************************************** + in_window.org.pkijs.copyBuffer = + function(input_buffer) + { + var result = new ArrayBuffer(input_buffer.byteLength); + + var resultView = new Uint8Array(result); + var inputView = new Uint8Array(input_buffer); + + for(var i = 0; i < inputView.length; i++) + resultView[i] = inputView[i]; + + return result; + }; + //************************************************************************************** + in_window.org.pkijs.getCrypto = + function() + { + var crypto_temp; + + if(local.engine.subtle !== null) + crypto_temp = local.engine.subtle; + + return crypto_temp; + }; + //************************************************************************************** + in_window.org.pkijs.stringPrep = + function(input_string) + { + /// String preparation function. In a future here will be realization of algorithm from RFC4518. + /// JavaScript string. As soon as for each ASN.1 string type we have a specific transformation function here we will work with pure JavaScript string + /// Formated string + + var result = input_string.replace(/^\s+|\s+$/g, ""); // Trim input string + result = result.replace(/\s+/g, " "); // Change all sequence of SPACE down to SPACE char + result = result.toLowerCase(); + + return result; + }; + //************************************************************************************** + in_window.org.pkijs.bufferToHexCodes = + function(input_buffer, input_offset, input_lenght) + { + var result = ""; + + var int_buffer = new Uint8Array(input_buffer, input_offset, input_lenght); + + for(var i = 0; i < int_buffer.length; i++) + { + var str = int_buffer[i].toString(16).toUpperCase(); + result = result + ((str.length === 1) ? "0" : "") + str; + } + + return result; + }; + //************************************************************************************** + in_window.org.pkijs.bufferFromHexCodes = + function(hexString) + { + /// Create an ArrayBuffer from string having hexdecimal codes + /// String to create ArrayBuffer from + + // #region Initial variables + var stringLength = hexString.length; + + var resultBuffer = new ArrayBuffer(stringLength >> 1); + var resultView = new Uint8Array(resultBuffer); + + var hex_map = {}; + + hex_map['0'] = 0x00; + hex_map['1'] = 0x01; + hex_map['2'] = 0x02; + hex_map['3'] = 0x03; + hex_map['4'] = 0x04; + hex_map['5'] = 0x05; + hex_map['6'] = 0x06; + hex_map['7'] = 0x07; + hex_map['8'] = 0x08; + hex_map['9'] = 0x09; + hex_map['A'] = 0x0A; + hex_map['a'] = 0x0A; + hex_map['B'] = 0x0B; + hex_map['b'] = 0x0B; + hex_map['C'] = 0x0C; + hex_map['c'] = 0x0C; + hex_map['D'] = 0x0D; + hex_map['d'] = 0x0D; + hex_map['E'] = 0x0E; + hex_map['e'] = 0x0E; + hex_map['F'] = 0x0F; + hex_map['f'] = 0x0F; + + var j = 0; + var temp = 0x00; + // #endregion + + // #region Convert char-by-char + for(var i = 0; i < stringLength; i++) + { + if(!(i % 2)) + temp = hex_map[hexString.charAt(i)] << 4; + else + { + temp |= hex_map[hexString.charAt(i)]; + + resultView[j] = temp; + j++; + } + } + // #endregion + + return resultBuffer; + }; + //************************************************************************************** + in_window.org.pkijs.getRandomValues = + function(view) + { + /// New array which gives a length for random value + + if(local.engine.crypto !== null) + return local.engine.crypto.getRandomValues(view); + else + throw new Error("No support for Web Cryptography API"); + }; + //************************************************************************************** + in_window.org.pkijs.getAlgorithmParameters = + function(algorithmName, operation) + { + /// Algorithm name to get common parameters for + /// Kind of operation: "sign", "encrypt", "generatekey", "importkey", "exportkey", "verify" + + var result = { + algorithm: {}, + usages: [] + }; + + switch(algorithmName.toUpperCase()) + { + case "RSASSA-PKCS1-V1_5": + switch(operation.toLowerCase()) + { + case "generatekey": + result = { + algorithm: { + name: "RSASSA-PKCS1-v1_5", + modulusLength: 2048, + publicExponent: new Uint8Array([0x01, 0x00, 0x01]), + hash: { + name: "SHA-256" + } + }, + usages: ["sign", "verify"] + }; + break; + case "verify": + case "sign": + case "importkey": + result = { + algorithm: { + name: "RSASSA-PKCS1-v1_5", + hash: { + name: "SHA-256" + } + }, + usages: ["verify"] // For importKey("pkcs8") usage must be "sign" only + }; + break; + case "exportkey": + default: + return { + algorithm: { + name: "RSASSA-PKCS1-v1_5" + }, + usages: [] + }; + } + break; + case "RSA-PSS": + switch(operation.toLowerCase()) + { + case "sign": + case "verify": + result = { + algorithm: { + name: "RSA-PSS", + hash: { + name: "SHA-1" + }, + saltLength: 20 + }, + usages: ["sign", "verify"] + }; + break; + case "generatekey": + result = { + algorithm: { + name: "RSA-PSS", + modulusLength: 2048, + publicExponent: new Uint8Array([0x01, 0x00, 0x01]), + hash: { + name: "SHA-1" + } + }, + usages: ["sign", "verify"] + }; + break; + case "importkey": + result = { + algorithm: { + name: "RSA-PSS", + hash: { + name: "SHA-1" + } + }, + usages: ["verify"] // For importKey("pkcs8") usage must be "sign" only + }; + break; + case "exportkey": + default: + return { + algorithm: { + name: "RSA-PSS" + }, + usages: [] + }; + } + break; + case "RSA-OAEP": + switch(operation.toLowerCase()) + { + case "encrypt": + case "decrypt": + result = { + algorithm: { + name: "RSA-OAEP" + }, + usages: ["encrypt", "decrypt"] + }; + break; + break; + case "generatekey": + result = { + algorithm: { + name: "RSA-OAEP", + modulusLength: 2048, + publicExponent: new Uint8Array([0x01, 0x00, 0x01]), + hash: { + name: "SHA-256" + } + }, + usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"] + }; + break; + case "importkey": + result = { + algorithm: { + name: "RSA-OAEP", + hash: { + name: "SHA-256" + } + }, + usages: ["encrypt"] // encrypt for "spki" and decrypt for "pkcs8" + }; + break; + case "exportkey": + default: + return { + algorithm: { + name: "RSA-OAEP" + }, + usages: [] + }; + } + break; + case "ECDSA": + switch(operation.toLowerCase()) + { + case "generatekey": + result = { + algorithm: { + name: "ECDSA", + namedCurve: "P-256" + }, + usages: ["sign", "verify"] + }; + break; + case "importkey": + result = { + algorithm: { + name: "ECDSA", + namedCurve: "P-256" + }, + usages: ["verify"] // "sign" for "pkcs8" + }; + break; + case "verify": + case "sign": + result = { + algorithm: { + name: "ECDSA", + hash: { + name: "SHA-256" + } + }, + usages: ["sign"] + }; + break; + default: + return { + algorithm: { + name: "ECDSA" + }, + usages: [] + }; + } + break; + case "ECDH": + switch(operation.toLowerCase()) + { + case "exportkey": + case "importkey": + case "generatekey": + result = { + algorithm: { + name: "ECDH", + namedCurve: "P-256" + }, + usages: ["deriveKey", "deriveBits"] + }; + break; + case "derivekey": + case "derivebits": + result = { + algorithm: { + name: "ECDH", + namedCurve: "P-256", + public: [] // Must be a "publicKey" + }, + usages: ["encrypt", "decrypt"] + }; + break; + default: + return { + algorithm: { + name: "ECDH" + }, + usages: [] + }; + } + break; + case "AES-CTR": + switch(operation.toLowerCase()) + { + case "importkey": + case "exportkey": + case "generatekey": + result = { + algorithm: { + name: "AES-CTR", + length: 256 + }, + usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"] + }; + break; + case "decrypt": + case "encrypt": + result = { + algorithm: { + name: "AES-CTR", + counter: new Uint8Array(16), + length: 10 + }, + usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"] + }; + break; + default: + return { + algorithm: { + name: "AES-CTR" + }, + usages: [] + }; + } + break; + case "AES-CBC": + switch(operation.toLowerCase()) + { + case "importkey": + case "exportkey": + case "generatekey": + result = { + algorithm: { + name: "AES-CBC", + length: 256 + }, + usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"] + }; + break; + case "decrypt": + case "encrypt": + result = { + algorithm: { + name: "AES-CBC", + iv: in_window.org.pkijs.getRandomValues(new Uint8Array(16)) // For "decrypt" the value should be replaced with value got on "encrypt" step + }, + usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"] + }; + break; + default: + return { + algorithm: { + name: "AES-CBC" + }, + usages: [] + }; + } + break; + case "AES-GCM": + switch(operation.toLowerCase()) + { + case "importkey": + case "exportkey": + case "generatekey": + result = { + algorithm: { + name: "AES-GCM", + length: 256 + }, + usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"] + }; + break; + case "decrypt": + case "encrypt": + result = { + algorithm: { + name: "AES-GCM", + iv: in_window.org.pkijs.getRandomValues(new Uint8Array(16)) // For "decrypt" the value should be replaced with value got on "encrypt" step + }, + usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"] + }; + break; + default: + return { + algorithm: { + name: "AES-GCM" + }, + usages: [] + }; + } + break; + case "AES-KW": + switch(operation.toLowerCase()) + { + case "importkey": + case "exportkey": + case "generatekey": + case "wrapkey": + case "unwrapkey": + result = { + algorithm: { + name: "AES-KW", + length: 256 + }, + usages: ["wrapKey", "unwrapKey"] + }; + break; + default: + return { + algorithm: { + name: "AES-KW" + }, + usages: [] + }; + } + break; + case "HMAC": + switch(operation.toLowerCase()) + { + case "sign": + case "verify": + result = { + algorithm: { + name: "HMAC" + }, + usages: ["sign", "verify"] + }; + break; + case "importkey": + case "exportkey": + case "generatekey": + result = { + algorithm: { + name: "HMAC", + length: 32, + hash: { + name: "SHA-256" + } + }, + usages: ["sign", "verify"] + }; + break; + default: + return { + algorithm: { + name: "HMAC" + }, + usages: [] + }; + } + break; + case "HKDF": + switch(operation.toLowerCase()) + { + case "derivekey": + result = { + algorithm: { + name: "HKDF", + hash: "SHA-256", + salt: new Uint8Array(), + info: new Uint8Array() + }, + usages: ["encrypt", "decrypt"] + }; + break; + default: + return { + algorithm: { + name: "HKDF" + }, + usages: [] + }; + } + break; + case "PBKDF2": + switch(operation.toLowerCase()) + { + case "derivekey": + result = { + algorithm: { + name: "PBKDF2", + hash: { name: "SHA-256" }, + salt: new Uint8Array(), + iterations: 1000 + }, + usages: ["encrypt", "decrypt"] + }; + break; + default: + return { + algorithm: { + name: "PBKDF2" + }, + usages: [] + }; + } + break; + default: + ; + } + + return result; + }; + //************************************************************************************** + in_window.org.pkijs.getOIDByAlgorithm = + function(algorithm) + { + /// Get OID for each specific WebCrypto algorithm + /// WebCrypto algorithm + + var result = ""; + + switch(algorithm.name.toUpperCase()) + { + case "RSASSA-PKCS1-V1_5": + switch(algorithm.hash.name.toUpperCase()) + { + case "SHA-1": + result = "1.2.840.113549.1.1.5"; + break; + case "SHA-256": + result = "1.2.840.113549.1.1.11"; + break; + case "SHA-384": + result = "1.2.840.113549.1.1.12"; + break; + case "SHA-512": + result = "1.2.840.113549.1.1.13"; + break; + default:; + } + break; + case "RSA-PSS": + result = "1.2.840.113549.1.1.10"; + break; + case "RSA-OAEP": + result = "1.2.840.113549.1.1.7"; + break; + case "ECDSA": + switch(algorithm.hash.name.toUpperCase()) + { + case "SHA-1": + result = "1.2.840.10045.4.1"; + break; + case "SHA-256": + result = "1.2.840.10045.4.3.2"; + break; + case "SHA-384": + result = "1.2.840.10045.4.3.3"; + break; + case "SHA-512": + result = "1.2.840.10045.4.3.4"; + break; + default:; + } + break; + case "ECDH": + switch(algorithm.kdf.toUpperCase()) // Non-standard addition - hash algorithm of KDF function + { + case "SHA-1": + result = "1.3.133.16.840.63.0.2"; // dhSinglePass-stdDH-sha1kdf-scheme + break; + case "SHA-256": + result = "1.3.132.1.11.1"; // dhSinglePass-stdDH-sha256kdf-scheme + break; + case "SHA-384": + result = "1.3.132.1.11.2"; // dhSinglePass-stdDH-sha384kdf-scheme + break; + case "SHA-512": + result = "1.3.132.1.11.3"; // dhSinglePass-stdDH-sha512kdf-scheme + break; + default:; + } + break; + case "AES-CTR": + break; + case "AES-CBC": + switch(algorithm.length) + { + case 128: + result = "2.16.840.1.101.3.4.1.2"; + break; + case 192: + result = "2.16.840.1.101.3.4.1.22"; + break; + case 256: + result = "2.16.840.1.101.3.4.1.42"; + break; + default:; + } + break; + case "AES-CMAC": + break; + case "AES-GCM": + switch(algorithm.length) + { + case 128: + result = "2.16.840.1.101.3.4.1.6"; + break; + case 192: + result = "2.16.840.1.101.3.4.1.26"; + break; + case 256: + result = "2.16.840.1.101.3.4.1.46"; + break; + default:; + } + break; + case "AES-CFB": + switch(algorithm.length) + { + case 128: + result = "2.16.840.1.101.3.4.1.4"; + break; + case 192: + result = "2.16.840.1.101.3.4.1.24"; + break; + case 256: + result = "2.16.840.1.101.3.4.1.44"; + break; + default:; + } + break; + case "AES-KW": + switch(algorithm.length) + { + case 128: + result = "2.16.840.1.101.3.4.1.5"; + break; + case 192: + result = "2.16.840.1.101.3.4.1.25"; + break; + case 256: + result = "2.16.840.1.101.3.4.1.45"; + break; + default:; + } + break; + case "HMAC": + switch(algorithm.hash.name.toUpperCase()) + { + case "SHA-1": + result = "1.2.840.113549.2.7"; + break; + case "SHA-256": + result = "1.2.840.113549.2.9"; + break; + case "SHA-384": + result = "1.2.840.113549.2.10"; + break; + case "SHA-512": + result = "1.2.840.113549.2.11"; + break; + default:; + } + break; + case "DH": + result = "1.2.840.113549.1.9.16.3.5"; + break; + case "SHA-1": + result = "1.3.14.3.2.26"; + break; + case "SHA-256": + result = "2.16.840.1.101.3.4.2.1"; + break; + case "SHA-384": + result = "2.16.840.1.101.3.4.2.2"; + break; + case "SHA-512": + result = "2.16.840.1.101.3.4.2.3"; + break; + case "CONCAT": + break; + case "HKDF": + break; + case "PBKDF2": + result = "1.2.840.113549.1.5.12"; + break; + // #region Special case - OIDs for ECC curves + case "P-256": + result = "1.2.840.10045.3.1.7"; + break; + case "P-384": + result = "1.3.132.0.34"; + break; + case "P-521": + result = "1.3.132.0.35"; + break; + // #endregion + default:; + } + + return result; + }; + //************************************************************************************** + in_window.org.pkijs.getAlgorithmByOID = + function(oid) + { + /// Get WebCrypto algorithm by wel-known OID + /// Wel-known OID to search for + + var result = {}; + + switch(oid) + { + case "1.2.840.113549.1.1.5": + result = { + name: "RSASSA-PKCS1-v1_5", + hash: { + name: "SHA-1" + } + }; + break; + case "1.2.840.113549.1.1.11": + result = { + name: "RSASSA-PKCS1-v1_5", + hash: { + name: "SHA-256" + } + }; + break; + case "1.2.840.113549.1.1.12": + result = { + name: "RSASSA-PKCS1-v1_5", + hash: { + name: "SHA-384" + } + }; + break; + case "1.2.840.113549.1.1.13": + result = { + name: "RSASSA-PKCS1-v1_5", + hash: { + name: "SHA-512" + } + }; + break; + case "1.2.840.113549.1.1.10": + result = { + name: "RSA-PSS" + }; + break; + case "1.2.840.113549.1.1.7": + result = { + name: "RSA-OAEP" + }; + break; + case "1.2.840.10045.4.1": + result = { + name: "ECDSA", + hash: { + name: "SHA-1" + } + }; + break; + case "1.2.840.10045.4.3.2": + result = { + name: "ECDSA", + hash: { + name: "SHA-256" + } + }; + break; + case "1.2.840.10045.4.3.3": + result = { + name: "ECDSA", + hash: { + name: "SHA-384" + } + }; + break; + case "1.2.840.10045.4.3.4": + result = { + name: "ECDSA", + hash: { + name: "SHA-512" + } + }; + break; + case "1.3.133.16.840.63.0.2": + result = { + name: "ECDH", + kdf: "SHA-1" + }; + break; + case "1.3.132.1.11.1": + result = { + name: "ECDH", + kdf: "SHA-256" + }; + break; + case "1.3.132.1.11.2": + result = { + name: "ECDH", + kdf: "SHA-384" + }; + break; + case "1.3.132.1.11.3": + result = { + name: "ECDH", + kdf: "SHA-512" + }; + break; + case "2.16.840.1.101.3.4.1.2": + result = { + name: "AES-CBC", + length: 128 + }; + break; + case "2.16.840.1.101.3.4.1.22": + result = { + name: "AES-CBC", + length: 192 + }; + break; + case "2.16.840.1.101.3.4.1.42": + result = { + name: "AES-CBC", + length: 256 + }; + break; + case "2.16.840.1.101.3.4.1.6": + result = { + name: "AES-GCM", + length: 128 + }; + break; + case "2.16.840.1.101.3.4.1.26": + result = { + name: "AES-GCM", + length: 192 + }; + break; + case "2.16.840.1.101.3.4.1.46": + result = { + name: "AES-GCM", + length: 256 + }; + break; + case "2.16.840.1.101.3.4.1.4": + result = { + name: "AES-CFB", + length: 128 + }; + break; + case "2.16.840.1.101.3.4.1.24": + result = { + name: "AES-CFB", + length: 192 + }; + break; + case "2.16.840.1.101.3.4.1.44": + result = { + name: "AES-CFB", + length: 256 + }; + break; + case "2.16.840.1.101.3.4.1.5": + result = { + name: "AES-KW", + length: 128 + }; + break; + case "2.16.840.1.101.3.4.1.25": + result = { + name: "AES-KW", + length: 192 + }; + break; + case "2.16.840.1.101.3.4.1.45": + result = { + name: "AES-KW", + length: 256 + }; + break; + case "1.2.840.113549.2.7": + result = { + name: "HMAC", + hash: { + name: "SHA-1" + } + }; + break; + case "1.2.840.113549.2.9": + result = { + name: "HMAC", + hash: { + name: "SHA-256" + } + }; + break; + case "1.2.840.113549.2.10": + result = { + name: "HMAC", + hash: { + name: "SHA-384" + } + }; + break; + case "1.2.840.113549.2.11": + result = { + name: "HMAC", + hash: { + name: "SHA-512" + } + }; + break; + case "1.2.840.113549.1.9.16.3.5": + result = { + name: "DH" + }; + break; + case "1.3.14.3.2.26": + result = { + name: "SHA-1" + }; + break; + case "2.16.840.1.101.3.4.2.1": + result = { + name: "SHA-256" + }; + break; + case "2.16.840.1.101.3.4.2.2": + result = { + name: "SHA-384" + }; + break; + case "2.16.840.1.101.3.4.2.3": + result = { + name: "SHA-512" + }; + break; + case "1.2.840.113549.1.5.12": + result = { + name: "PBKDF2" + }; + break; + // #region Special case - OIDs for ECC curves + case "1.2.840.10045.3.1.7": + result = { + name: "P-256", + size: 32 + }; + break; + case "1.3.132.0.34": + result = { + name: "P-384", + size: 48 + }; + break; + case "1.3.132.0.35": + result = { + name: "P-521", + size: 66 + }; + break; + // #endregion + default:; + } + + return result; + }; + //************************************************************************************** + in_window.org.pkijs.getHashAlgorithm = + function(signatureAlgorithm) + { + /// Getting hash algorithm by signature algorithm + /// Signature algorithm + + var result = ""; + + switch(signatureAlgorithm.algorithm_id) + { + case "1.2.840.10045.4.1": // ecdsa-with-SHA1 + case "1.2.840.113549.1.1.5": + result = "SHA-1"; + break; + case "1.2.840.10045.4.3.2": // ecdsa-with-SHA256 + case "1.2.840.113549.1.1.11": + result = "SHA-256"; + break; + case "1.2.840.10045.4.3.3": // ecdsa-with-SHA384 + case "1.2.840.113549.1.1.12": + result = "SHA-384"; + break; + case "1.2.840.10045.4.3.4": // ecdsa-with-SHA512 + case "1.2.840.113549.1.1.13": + result = "SHA-512"; + break; + case "1.2.840.113549.1.1.10": // RSA-PSS + { + var params; + + try + { + params = new in_window.org.pkijs.simpl.x509.RSASSA_PSS_params({ schema: signatureAlgorithm.algorithm_params }); + if("hashAlgorithm" in params) + { + var algorithm = in_window.org.pkijs.getAlgorithmByOID(params.hashAlgorithm.algorithm_id); + if(("name" in algorithm) === false) + return ""; + + result = algorithm.name; + } + else + result = "SHA-1"; + } + catch(ex) + { + } + } + break; + default:; + } + + return result; + }; + //************************************************************************************** + in_window.org.pkijs.createCMSECDSASignature = + function(signatureBuffer) + { + // #region Initial check for correct length + if((signatureBuffer.byteLength % 2) != 0) + return new ArrayBuffer(0); + // #endregion + + // #region Initial variables + var i = 0; + var length = signatureBuffer.byteLength / 2; // There are two equal parts inside incoming ArrayBuffer + + var signatureView = new Uint8Array(signatureBuffer); + + var r_buffer = new ArrayBuffer(length); + var r_view = new Uint8Array(r_buffer); + r_view.set(new Uint8Array(signatureBuffer, 0, length)); + var r_corrected_buffer; + var r_corrected_view; + + var s_buffer = new ArrayBuffer(length); + var s_view = new Uint8Array(s_buffer); + s_view.set(new Uint8Array(signatureBuffer, length, length)); + var s_corrected_buffer; + var s_corrected_view; + // #endregion + + // #region Get "r" part of ECDSA signature + switch(true) + { + case ((r_view[0] & 0x80) !== 0): + r_corrected_buffer = new ArrayBuffer(length + 1); + r_corrected_view = new Uint8Array(r_corrected_buffer); + + r_corrected_view[0] = 0x00; + + r_corrected_view.set(r_view, 1); + break; + case ((r_view[0] === 0x00) && ((r_view[1] & 0x80) === 0)): + r_corrected_buffer = new ArrayBuffer(length - 1); + r_corrected_view = new Uint8Array(r_corrected_buffer); + + r_corrected_view.set(new Uint8Array(signatureBuffer, 1, length - 1)); + break; + default: + r_corrected_buffer = r_buffer; + r_corrected_view = r_view; + } + // #endregion + + // #region Get "s" part of ECDSA signature + switch(true) + { + case ((s_view[0] & 0x80) !== 0): + s_corrected_buffer = new ArrayBuffer(length + 1); + s_corrected_view = new Uint8Array(s_corrected_buffer); + + s_corrected_view[0] = 0x00; + + s_corrected_view.set(s_view, 1); + break; + case ((s_view[0] === 0x00) && ((s_view[1] & 0x80) === 0)): + s_corrected_buffer = new ArrayBuffer(length - 1); + s_corrected_view = new Uint8Array(s_corrected_buffer); + + s_corrected_view.set(new Uint8Array(signatureBuffer, 1, length - 1)); + break; + default: + s_corrected_buffer = s_buffer; + s_corrected_view = s_view; + } + // #endregion + + // #region Create ASN.1 structure of CMS ECDSA signature + var r_integer = new in_window.org.pkijs.asn1.INTEGER(); + r_integer.value_block.is_hex_only = true; + r_integer.value_block.value_hex = in_window.org.pkijs.copyBuffer(r_corrected_buffer); + + var s_integer = new in_window.org.pkijs.asn1.INTEGER(); + s_integer.value_block.is_hex_only = true; + s_integer.value_block.value_hex = in_window.org.pkijs.copyBuffer(s_corrected_buffer); + + var asn1 = new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + r_integer, + s_integer + ] + }); + // #endregion + + return asn1.toBER(false); + } + //************************************************************************************** + in_window.org.pkijs.createECDSASignatureFromCMS = + function(cmsSignature) + { + // #region Initial variables + var sBuffer; + var rBuffer; + // #endregion + + // #region Check input variables + if((cmsSignature instanceof in_window.org.pkijs.asn1.SEQUENCE) === false) + return new ArrayBuffer(0); + + if(cmsSignature.value_block.value.length !== 2) + return new ArrayBuffer(0); + + if((cmsSignature.value_block.value[0] instanceof in_window.org.pkijs.asn1.INTEGER) === false) + return new ArrayBuffer(0); + + if((cmsSignature.value_block.value[1] instanceof in_window.org.pkijs.asn1.INTEGER) === false) + return new ArrayBuffer(0); + // #endregion + + // #region Aux functions + function transformINTEGER(integer) + { + var view = new Uint8Array(integer.value_block.value_hex); + + switch(integer.value_block.value_hex.byteLength) + { + case 32: + case 48: + case 66: + return integer.value_block.value_hex; + break; + case 33: + case 49: + case 67: + return (view.slice(1)).buffer; + break; + case 31: + case 47: + case 65: + { + var updatedBuffer = new ArrayBuffer(integer.value_block.value_hex.byteLength + 1); + var updatedView = new Uint8Array(updatedBuffer); + + updatedView.set(view, 1); + + return updatedBuffer; + } + break; + default: + return new ArrayBuffer(0); + } + } + // #endregion + + rBuffer = transformINTEGER(cmsSignature.value_block.value[0]); + sBuffer = transformINTEGER(cmsSignature.value_block.value[1]); + + return in_window.org.pkijs.concat_buffers(rBuffer, sBuffer); + } + //************************************************************************************** + in_window.org.pkijs.getEncryptionAlgorithm = + function(algorithm) + { + /// Get encryption algorithm OID by WebCrypto algorithm's object + /// WebCrypto algorithm object + + var result = ""; + + switch(algorithm.name.toUpperCase()) + { + case "AES-CBC": + switch(algorithm.length) + { + case 128: + result = "2.16.840.1.101.3.4.1.2"; + break; + case 192: + result = "2.16.840.1.101.3.4.1.22"; + break; + case 256: + result = "2.16.840.1.101.3.4.1.42"; + break; + default:; + } + break; + case "AES-GCM": + switch(algorithm.length) + { + case 128: + result = "2.16.840.1.101.3.4.1.6"; + break; + case 192: + result = "2.16.840.1.101.3.4.1.26"; + break; + case 256: + result = "2.16.840.1.101.3.4.1.46"; + break; + default:; + } + break; + default:; + } + + return result; + }; + //************************************************************************************** + in_window.org.pkijs.getAlgorithmByEncryptionOID = + function(oid) + { + /// Get encryption algorithm name by OID + /// OID of encryption algorithm + + var result = ""; + + switch(oid) + { + case "2.16.840.1.101.3.4.1.2": + case "2.16.840.1.101.3.4.1.22": + case "2.16.840.1.101.3.4.1.42": + result = "AES-CBC"; + break; + case "2.16.840.1.101.3.4.1.6": + case "2.16.840.1.101.3.4.1.26": + case "2.16.840.1.101.3.4.1.46": + result = "AES-GCM"; + break; + default:; + } + + return result; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** +} +)(typeof exports !== "undefined" ? exports : window); \ No newline at end of file diff --git a/express-server/node_modules/pkijs/org/pkijs/ocsp_tsp_schema.js b/express-server/node_modules/pkijs/org/pkijs/ocsp_tsp_schema.js new file mode 100644 index 00000000..0ce78634 --- /dev/null +++ b/express-server/node_modules/pkijs/org/pkijs/ocsp_tsp_schema.js @@ -0,0 +1,833 @@ +/* + * Copyright (c) 2014, GMO GlobalSign + * Copyright (c) 2015, Peculiar Ventures + * All rights reserved. + * + * Author 2014-2015, Yury Strozhevsky . + * + * 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 copyright holder 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. + * + */ +( +function(in_window) +{ + //************************************************************************************** + // #region Declaration of global variables + //************************************************************************************** + // #region "org" namespace + if(typeof in_window.org === "undefined") + in_window.org = {}; + else + { + if(typeof in_window.org !== "object") + throw new Error("Name org already exists and it's not an object"); + } + // #endregion + + // #region "org.pkijs" namespace + if(typeof in_window.org.pkijs === "undefined") + in_window.org.pkijs = {}; + else + { + if(typeof in_window.org.pkijs !== "object") + throw new Error("Name org.pkijs already exists and it's not an object" + " but " + (typeof in_window.org.pkijs)); + } + // #endregion + + // #region "org.pkijs.schema" namespace + if(typeof in_window.org.pkijs.schema === "undefined") + in_window.org.pkijs.schema = {}; + else + { + if(typeof in_window.org.pkijs.schema !== "object") + throw new Error("Name org.pkijs.schema already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.schema)); + } + // #endregion + + // #region "org.pkijs.schema.ocsp" namespace + if(typeof in_window.org.pkijs.schema.ocsp === "undefined") + in_window.org.pkijs.schema.ocsp = {}; + else + { + if(typeof in_window.org.pkijs.schema.ocsp !== "object") + throw new Error("Name org.pkijs.schema.ocsp already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.schema.ocsp)); + } + // #endregion + + // #region "org.pkijs.schema.tsp" namespace + if(typeof in_window.org.pkijs.schema.tsp === "undefined") + in_window.org.pkijs.schema.tsp = {}; + else + { + if(typeof in_window.org.pkijs.schema.tsp !== "object") + throw new Error("Name org.pkijs.schema.tsp already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.schema.tsp)); + } + // #endregion + + // #region "local" namespace + var local = {}; + // #endregion + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for OCSP request (RFC6960) + //************************************************************************************** + in_window.org.pkijs.schema.ocsp.CertID = + function() + { + //CertID ::= SEQUENCE { + // hashAlgorithm AlgorithmIdentifier, + // issuerNameHash OCTET STRING, -- Hash of issuer's DN + // issuerKeyHash OCTET STRING, -- Hash of issuer's public key + // serialNumber CertificateSerialNumber } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.hashAlgorithm_object || { + names: { + block_name: (names.hashAlgorithm || "") + } + }), + new in_window.org.pkijs.asn1.OCTETSTRING({ name: (names.issuerNameHash || "") }), + new in_window.org.pkijs.asn1.OCTETSTRING({ name: (names.issuerKeyHash || "") }), + new in_window.org.pkijs.asn1.INTEGER({ name: (names.serialNumber || "") }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.ocsp.Request = + function() + { + //Request ::= SEQUENCE { + // reqCert CertID, + // singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + in_window.org.pkijs.schema.ocsp.CertID(names.reqCert || {}), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [in_window.org.pkijs.schema.EXTENSIONS(names.extensions || { + names: { + block_name: (names.singleRequestExtensions || "") + } + })] + }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.ocsp.TBSRequest = + function() + { + //TBSRequest ::= SEQUENCE { + // version [0] EXPLICIT Version DEFAULT v1, + // requestorName [1] EXPLICIT GeneralName OPTIONAL, + // requestList SEQUENCE OF Request, + // requestExtensions [2] EXPLICIT Extensions OPTIONAL } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || "TBSRequest"), + value: [ + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [new in_window.org.pkijs.asn1.INTEGER({ name: (names.TBSRequest_version || "TBSRequest.version") })] + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [in_window.org.pkijs.schema.GENERAL_NAME(names.requestorName || { + names: { + block_name: "TBSRequest.requestorName" + } + })] + }), + new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.requestList || "TBSRequest.requestList"), + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.requests || "TBSRequest.requests"), + value: in_window.org.pkijs.schema.ocsp.Request(names.requestNames || {}) + }) + ] + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 2 // [2] + }, + value: [in_window.org.pkijs.schema.EXTENSIONS(names.extensions || { + names: { + block_name: (names.requestExtensions || "TBSRequest.requestExtensions") + } + })] + }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.ocsp.Signature = + function() + { + //Signature ::= SEQUENCE { + // signatureAlgorithm AlgorithmIdentifier, + // signature BIT STRING, + // certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.signatureAlgorithm || {}), + new in_window.org.pkijs.asn1.BITSTRING({ name: (names.signature || "") }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [ + new in_window.org.pkijs.asn1.SEQUENCE({ + value: [new in_window.org.pkijs.asn1.REPEATED({ + name: (names.certs || ""), + value: in_window.org.pkijs.schema.CERT(names.certs || {}) + })] + }) + ] + }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.OCSP_REQUEST = + function() + { + //OCSPRequest ::= SEQUENCE { + // tbsRequest TBSRequest, + // optionalSignature [0] EXPLICIT Signature OPTIONAL } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: names.block_name || "OCSPRequest", + value: [ + in_window.org.pkijs.schema.ocsp.TBSRequest(names.tbsRequest || { + names: { + block_name: "tbsRequest" + } + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [ + in_window.org.pkijs.schema.ocsp.Signature(names.optionalSignature || { + names: { + block_name: "optionalSignature" + } + }) + ] + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "ResponderID" type + //************************************************************************************** + in_window.org.pkijs.schema.ocsp.ResponderID = + function() + { + // KeyHash ::= OCTET STRING + // + // ResponderID ::= CHOICE { + // byName [1] Name, + // byKey [2] KeyHash } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.CHOICE({ + value: [ + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + name: (names.block_name || ""), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [in_window.org.pkijs.schema.RDN(names.byName || { + names: { + block_name: "" + } + })] + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + name: (names.block_name || ""), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 2 // [2] + }, + value: [new in_window.org.pkijs.asn1.OCTETSTRING({ name: (names.byKey || "") })] + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for OCSP response (RFC6960) + //************************************************************************************** + in_window.org.pkijs.schema.ocsp.ResponseBytes = + function() + { + //ResponseBytes ::= SEQUENCE { + // responseType OBJECT IDENTIFIER, + // response OCTET STRING } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.OID({ name: (names.responseType || "") }), + new in_window.org.pkijs.asn1.OCTETSTRING({ name: (names.response || "") }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.OCSP_RESPONSE = + function() + { + //OCSPResponse ::= SEQUENCE { + // responseStatus OCSPResponseStatus, + // responseBytes [0] EXPLICIT ResponseBytes OPTIONAL } + // + //OCSPResponseStatus ::= ENUMERATED { + // successful (0), -- Response has valid confirmations + // malformedRequest (1), -- Illegal confirmation request + // internalError (2), -- Internal error in issuer + // tryLater (3), -- Try again later + // -- (4) is not used + // sigRequired (5), -- Must sign the request + // unauthorized (6) -- Request unauthorized + //} + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || "OCSPResponse"), + value: [ + new in_window.org.pkijs.asn1.ENUMERATED({ name: (names.responseStatus || "responseStatus") }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [ + in_window.org.pkijs.schema.ocsp.ResponseBytes(names.responseBytes || { + names: { + block_name: "responseBytes" + } + }) + ] + }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.ocsp.SingleResponse = + function() + { + //SingleResponse ::= SEQUENCE { + // certID CertID, + // certStatus CertStatus, + // thisUpdate GeneralizedTime, + // nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL, + // singleExtensions [1] EXPLICIT Extensions OPTIONAL } + // + //CertStatus ::= CHOICE { + // good [0] IMPLICIT NULL, + // revoked [1] IMPLICIT RevokedInfo, + // unknown [2] IMPLICIT UnknownInfo } + // + //RevokedInfo ::= SEQUENCE { + // revocationTime GeneralizedTime, + // revocationReason [0] EXPLICIT CRLReason OPTIONAL } + // + //UnknownInfo ::= NULL + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + in_window.org.pkijs.schema.ocsp.CertID(names.certID || {}), + new in_window.org.pkijs.asn1.CHOICE({ + value: [ + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + name: (names.certStatus || ""), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + len_block_length: 1 // The length contains one byte 0x00 + }), // IMPLICIT NULL (no "value_block") + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + name: (names.certStatus || ""), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [ + new in_window.org.pkijs.asn1.GENERALIZEDTIME(), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [new in_window.org.pkijs.asn1.ENUMERATED()] + }) + ] + }), + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + name: (names.certStatus || ""), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 2 // [2] + }, + len_block: { length: 1 } + }) // IMPLICIT NULL (no "value_block") + ] + }), + new in_window.org.pkijs.asn1.GENERALIZEDTIME({ name: (names.thisUpdate || "") }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [new in_window.org.pkijs.asn1.GENERALIZEDTIME({ name: (names.nextUpdate || "") })] + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [in_window.org.pkijs.schema.EXTENSIONS(names.singleExtensions || {})] + }) // EXPLICIT SEQUENCE value + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.ocsp.ResponseData = + function() + { + //ResponseData ::= SEQUENCE { + // version [0] EXPLICIT Version DEFAULT v1, + // responderID ResponderID, + // producedAt GeneralizedTime, + // responses SEQUENCE OF SingleResponse, + // responseExtensions [1] EXPLICIT Extensions OPTIONAL } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || "ResponseData"), + value: [ + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [new in_window.org.pkijs.asn1.INTEGER({ name: (names.version || "ResponseData.version") })] + }), + new in_window.org.pkijs.asn1.CHOICE({ + value: [ + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + name: (names.responderID || "ResponseData.responderID"), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [in_window.org.pkijs.schema.RDN(names.ResponseData_byName || { + names: { + block_name: "ResponseData.byName" + } + })] + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + name: (names.responderID || "ResponseData.responderID"), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 2 // [2] + }, + value: [new in_window.org.pkijs.asn1.OCTETSTRING({ name: (names.ResponseData_byKey || "ResponseData.byKey") })] + }) + ] + }), + new in_window.org.pkijs.asn1.GENERALIZEDTIME({ name: (names.producedAt || "ResponseData.producedAt") }), + new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: "ResponseData.responses", + value: in_window.org.pkijs.schema.ocsp.SingleResponse(names.response || {}) + }) + ] + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [in_window.org.pkijs.schema.EXTENSIONS(names.extensions || { + names: { + block_name: "ResponseData.responseExtensions" + } + })] + }) // EXPLICIT SEQUENCE value + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.OCSP_BASIC_RESPONSE = + function() + { + //BasicOCSPResponse ::= SEQUENCE { + // tbsResponseData ResponseData, + // signatureAlgorithm AlgorithmIdentifier, + // signature BIT STRING, + // certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || "BasicOCSPResponse"), + value: [ + in_window.org.pkijs.schema.ocsp.ResponseData(names.tbsResponseData || { + names: { + block_name: "BasicOCSPResponse.tbsResponseData" + } + }), + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.signatureAlgorithm || { + names: { + block_name: "BasicOCSPResponse.signatureAlgorithm" + } + }), + new in_window.org.pkijs.asn1.BITSTRING({ name: (names.signature || "BasicOCSPResponse.signature") }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [ + new in_window.org.pkijs.asn1.SEQUENCE({ + value: [new in_window.org.pkijs.asn1.REPEATED({ + name: "BasicOCSPResponse.certs", + value: in_window.org.pkijs.schema.CERT(names.certs || {}) + })] + }) + ] + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for Time-stamp request type (RFC3161) + //************************************************************************************** + in_window.org.pkijs.schema.tsp.MessageImprint = + function() + { + //MessageImprint ::= SEQUENCE { + // hashAlgorithm AlgorithmIdentifier, + // hashedMessage OCTET STRING } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.hashAlgorithm || {}), + new in_window.org.pkijs.asn1.OCTETSTRING({ name: (names.hashedMessage || "") }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.TSP_REQUEST = + function() + { + //TimeStampReq ::= SEQUENCE { + // version INTEGER { v1(1) }, + // messageImprint MessageImprint, + // reqPolicy TSAPolicyId OPTIONAL, + // nonce INTEGER OPTIONAL, + // certReq BOOLEAN DEFAULT FALSE, + // extensions [0] IMPLICIT Extensions OPTIONAL } + // + //TSAPolicyId ::= OBJECT IDENTIFIER + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || "TimeStampReq"), + value: [ + new in_window.org.pkijs.asn1.INTEGER({ name: (names.version || "TimeStampReq.version") }), + in_window.org.pkijs.schema.tsp.MessageImprint(names.messageImprint || { + names: { + block_name: "TimeStampReq.messageImprint" + } + }), + new in_window.org.pkijs.asn1.OID({ + name: (names.reqPolicy || "TimeStampReq.reqPolicy"), + optional: true + }), + new in_window.org.pkijs.asn1.INTEGER({ + name: (names.nonce || "TimeStampReq.nonce"), + optional: true + }), + new in_window.org.pkijs.asn1.BOOLEAN({ + name: (names.certReq || "TimeStampReq.certReq"), + optional: true + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [new in_window.org.pkijs.asn1.REPEATED({ + name: (names.extensions || "TimeStampReq.extensions"), + value: in_window.org.pkijs.schema.EXTENSION() + })] + }) // IMPLICIT SEQUENCE value + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for Time-stamp response (RFC3161) + //************************************************************************************** + in_window.org.pkijs.schema.tsp.Accuracy = + function() + { + //Accuracy ::= SEQUENCE { + // seconds INTEGER OPTIONAL, + // millis [0] INTEGER (1..999) OPTIONAL, + // micros [1] INTEGER (1..999) OPTIONAL } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + optional: true, + value: [ + new in_window.org.pkijs.asn1.INTEGER({ + optional: true, + name: (names.seconds || "") + }), + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + name: (names.millis || ""), + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + } + }), + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + name: (names.micros || ""), + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + } + }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.TST_INFO = + function() + { + //TSTInfo ::= SEQUENCE { + // version INTEGER { v1(1) }, + // policy TSAPolicyId, + // messageImprint MessageImprint, + // serialNumber INTEGER, + // genTime GeneralizedTime, + // accuracy Accuracy OPTIONAL, + // ordering BOOLEAN DEFAULT FALSE, + // nonce INTEGER OPTIONAL, + // tsa [0] GeneralName OPTIONAL, + // extensions [1] IMPLICIT Extensions OPTIONAL } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || "TSTInfo"), + value: [ + new in_window.org.pkijs.asn1.INTEGER({ name: (names.version || "TSTInfo.version") }), + new in_window.org.pkijs.asn1.OID({ name: (names.policy || "TSTInfo.policy") }), + in_window.org.pkijs.schema.tsp.MessageImprint(names.messageImprint || { + names: { + block_name: "TSTInfo.messageImprint" + } + }), + new in_window.org.pkijs.asn1.INTEGER({ name: (names.serialNumber || "TSTInfo.serialNumber") }), + new in_window.org.pkijs.asn1.GENERALIZEDTIME({ name: (names.genTime || "TSTInfo.genTime") }), + in_window.org.pkijs.schema.tsp.Accuracy(names.accuracy || { + names: { + block_name: "TSTInfo.accuracy" + } + }), + new in_window.org.pkijs.asn1.BOOLEAN({ + name: (names.ordering || "TSTInfo.ordering"), + optional: true + }), + new in_window.org.pkijs.asn1.INTEGER({ + name: (names.nonce || "TSTInfo.nonce"), + optional: true + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [in_window.org.pkijs.schema.GENERAL_NAME(names.tsa || { + names: { + block_name: "TSTInfo.tsa" + } + })] + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.extensions || "TSTInfo.extensions"), + value: in_window.org.pkijs.schema.EXTENSION(names.extension || {}) + }) + ] + }) // IMPLICIT Extensions + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.tsp.PKIStatusInfo = + function() + { + //PKIStatusInfo ::= SEQUENCE { + // status PKIStatus, + // statusString PKIFreeText OPTIONAL, + // failInfo PKIFailureInfo OPTIONAL } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.INTEGER({ name: (names.status || "") }), + new in_window.org.pkijs.asn1.SEQUENCE({ + optional: true, + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.statusStrings || ""), + value: new in_window.org.pkijs.asn1.UTF8STRING() + }) + ] + }), + new in_window.org.pkijs.asn1.BITSTRING({ + name: (names.failInfo || ""), + optional: true + }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.TSP_RESPONSE = + function() + { + //TimeStampResp ::= SEQUENCE { + // status PKIStatusInfo, + // timeStampToken TimeStampToken OPTIONAL } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || "TimeStampResp"), + value: [ + in_window.org.pkijs.schema.tsp.PKIStatusInfo(names.status || { + names: { + block_name: "TimeStampResp.status" + } + }), + in_window.org.pkijs.schema.CMS_CONTENT_INFO(names.timeStampToken || { + names: { + block_name: "TimeStampResp.timeStampToken" + } + }, true) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** +} +)(typeof exports !== "undefined" ? exports : window); \ No newline at end of file diff --git a/express-server/node_modules/pkijs/org/pkijs/ocsp_tsp_simpl.js b/express-server/node_modules/pkijs/org/pkijs/ocsp_tsp_simpl.js new file mode 100644 index 00000000..87368f0d --- /dev/null +++ b/express-server/node_modules/pkijs/org/pkijs/ocsp_tsp_simpl.js @@ -0,0 +1,3089 @@ +/* + * Copyright (c) 2014, GMO GlobalSign + * Copyright (c) 2015, Peculiar Ventures + * All rights reserved. + * + * Author 2014-2015, Yury Strozhevsky . + * + * 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 copyright holder 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. + * + */ +( +function(in_window) +{ + //************************************************************************************** + // #region Declaration of global variables + //************************************************************************************** + // #region "org" namespace + if(typeof in_window.org === "undefined") + in_window.org = {}; + else + { + if(typeof in_window.org !== "object") + throw new Error("Name org already exists and it's not an object"); + } + // #endregion + + // #region "org.pkijs" namespace + if(typeof in_window.org.pkijs === "undefined") + in_window.org.pkijs = {}; + else + { + if(typeof in_window.org.pkijs !== "object") + throw new Error("Name org.pkijs already exists and it's not an object" + " but " + (typeof in_window.org.pkijs)); + } + // #endregion + + // #region "org.pkijs.simpl" namespace + if(typeof in_window.org.pkijs.simpl === "undefined") + in_window.org.pkijs.simpl = {}; + else + { + if(typeof in_window.org.pkijs.simpl !== "object") + throw new Error("Name org.pkijs.simpl already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.simpl)); + } + // #endregion + + // #region "org.pkijs.simpl.ocsp" namespace + if(typeof in_window.org.pkijs.simpl.ocsp === "undefined") + in_window.org.pkijs.simpl.ocsp = {}; + else + { + if(typeof in_window.org.pkijs.simpl.ocsp !== "object") + throw new Error("Name org.pkijs.simpl.ocsp already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.simpl.ocsp)); + } + // #endregion + + // #region "org.pkijs.simpl.tsp" namespace + if(typeof in_window.org.pkijs.simpl.tsp === "undefined") + in_window.org.pkijs.simpl.tsp = {}; + else + { + if(typeof in_window.org.pkijs.simpl.tsp !== "object") + throw new Error("Name org.pkijs.simpl.tsp already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.simpl.tsp)); + } + // #endregion + + // #region "local" namespace + var local = {}; + // #endregion + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "CertID" type + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.CertID = + function() + { + // #region Internal properties of the object + this.hashAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.issuerNameHash = new in_window.org.pkijs.asn1.OCTETSTRING(); + this.issuerKeyHash = new in_window.org.pkijs.asn1.OCTETSTRING(); + this.serialNumber = new in_window.org.pkijs.asn1.INTEGER(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.ocsp.CertID.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.hashAlgorithm = arguments[0].hashAlgorithm || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.issuerNameHash = arguments[0].issuerNameHash || new in_window.org.pkijs.asn1.OCTETSTRING(); + this.issuerKeyHash = arguments[0].issuerKeyHash || new in_window.org.pkijs.asn1.OCTETSTRING(); + this.serialNumber = arguments[0].serialNumber || new in_window.org.pkijs.asn1.INTEGER(); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.CertID.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.ocsp.CertID({ + names: { + hashAlgorithm: "hashAlgorithm", + issuerNameHash: "issuerNameHash", + issuerKeyHash: "issuerKeyHash", + serialNumber: "serialNumber" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for CertID"); + // #endregion + + // #region Get internal properties from parsed schema + this.hashAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["hashAlgorithm"] }); + this.issuerNameHash = asn1.result["issuerNameHash"]; + this.issuerKeyHash = asn1.result["issuerKeyHash"]; + this.serialNumber = asn1.result["serialNumber"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.CertID.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + this.hashAlgorithm.toSchema(), + this.issuerNameHash, + this.issuerKeyHash, + this.serialNumber + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.CertID.prototype.toJSON = + function() + { + return { + hashAlgorithm: this.hashAlgorithm.toJSON(), + issuerNameHash: this.issuerNameHash.toJSON(), + issuerKeyHash: this.issuerKeyHash.toJSON(), + serialNumber: this.serialNumber.toJSON() + }; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.CertID.prototype.isEqual = + function(certificateID) + { + /// Check that two "CertIDs" are equal + /// Identifier of the certificate to be checked + + // #region Check "hashAlgorithm" + if(!this.hashAlgorithm.algorithm_id == certificateID.hashAlgorithm.algorithm_id) + return false; + // #endregion + + // #region Check "issuerNameHash" + if(in_window.org.pkijs.isEqual_buffer(this.issuerNameHash.value_block.value_hex, certificateID.issuerNameHash.value_block.value_hex) == false) + return false; + // #endregion + + // #region Check "issuerKeyHash" + if(in_window.org.pkijs.isEqual_buffer(this.issuerKeyHash.value_block.value_hex, certificateID.issuerKeyHash.value_block.value_hex) == false) + return false; + // #endregion + + // #region Check "serialNumber" + if(!this.serialNumber.isEqual(certificateID.serialNumber)) + return false; + // #endregion + + return true; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.CertID.prototype.createForCertificate = + function(certificate, parameters) + { + /// Making OCSP certificate identifier for specific certificate + /// Certificate making OCSP Request for + /// Additional parameters + + // #region Initial variables + var _this = this; + var sequence = Promise.resolve(); + + var issuerCertificate; + + var hashOID; + + var issuerNameHash; + var issuerKeyHash; + // #endregion + + // #region Get a "crypto" extension + var crypto = in_window.org.pkijs.getCrypto(); + if(typeof crypto == "undefined") + return Promise.reject("Unable to create WebCrypto object"); + // #endregion + + // #region Check input parameters + if(("hashAlgorithm" in parameters) == false) + return Promise.reject("Parameter \"hashAlgorithm\" is mandatory for \"OCSP_REQUEST.createForCertificate\""); + + hashOID = in_window.org.pkijs.getOIDByAlgorithm({ name: parameters.hashAlgorithm }); + if(hashOID === "") + return Promise.reject("Incorrect \"hashAlgorithm\": " + this.hashAlgorithm); + + this.hashAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: hashOID, + algorithm_params: new in_window.org.pkijs.asn1.NULL() + }); + + if("issuerCertificate" in parameters) + issuerCertificate = parameters.issuerCertificate; + else + return Promise.reject("Parameter \"issuerCertificate\" is mandatory for \"OCSP_REQUEST.createForCertificate\""); + // #endregion + + // #region Initialize "serialNumber" field + this.serialNumber = certificate.serialNumber; + // #endregion + + // #region Create "issuerNameHash" + sequence = sequence.then( + function(result) + { + var issuerNameBuffer = issuerCertificate.subject.toSchema().toBER(false); + + return crypto.digest({ name: parameters.hashAlgorithm }, issuerNameBuffer); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + // #region Create "issuerKeyHash" + sequence = sequence.then( + function(result) + { + _this.issuerNameHash = new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: result }); + + var issuerKeyBuffer = issuerCertificate.subjectPublicKeyInfo.subjectPublicKey.value_block.value_hex; + + return crypto.digest({ name: parameters.hashAlgorithm }, issuerKeyBuffer); + }, + function(error) + { + return Promise.reject(error); + } + ).then( + function(result) + { + _this.issuerKeyHash = new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: result }); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + return sequence; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "Request" type + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.Request = + function() + { + // #region Internal properties of the object + this.reqCert = new in_window.org.pkijs.simpl.ocsp.CertID(); + // OPTIONAL this.singleRequestExtensions = new Array(); // Array of in_window.org.pkijs.simpl.EXTENSION(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.ocsp.Request.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.reqCert = arguments[0].reqCert || new in_window.org.pkijs.simpl.ocsp.CertID(); + if("singleRequestExtensions" in arguments[0]) + this.singleRequestExtensions = arguments[0].singleRequestExtensions; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.Request.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.ocsp.Request({ + names: { + reqCert: { + names: { + block_name: "reqCert" + } + }, + singleRequestExtensions: { + names: { + block_name: "singleRequestExtensions" + } + } + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for Request"); + // #endregion + + // #region Get internal properties from parsed schema + this.reqCert = new in_window.org.pkijs.simpl.ocsp.CertID({ schema: asn1.result["reqCert"] }); + + if("singleRequestExtensions" in asn1.result) + { + this.singleRequestExtensions = new Array(); + var exts = asn1.result["singleRequestExtensions"].value_block.value; + + for(var i = 0; i < exts.length; i++) + this.singleRequestExtensions.push(new in_window.org.pkijs.simpl.EXTENSION({ schema: exts[i] })); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.Request.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + output_array.push(this.reqCert.toSchema()); + + if("singleRequestExtensions" in this) + { + var extensions = new Array(); + + for(var j = 0; j < this.singleRequestExtensions.length; j++) + extensions.push(this.singleRequestExtensions[j].toSchema()); + + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [ + new in_window.org.pkijs.asn1.SEQUENCE({ + value: extensions + }) + ] + })); + } + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.Request.prototype.toJSON = + function() + { + var _object = { + reqCert: this.reqCert.toJSON() + }; + + if("singleRequestExtensions" in this) + { + _object.singleRequestExtensions = new Array(); + + for(var i = 0; i < this.singleRequestExtensions.length; i++) + _object.singleRequestExtensions.push(this.singleRequestExtensions[i].toJSON()); + } + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "TBSRequest" type + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.TBSRequest = + function() + { + // #region Internal properties of the object + this.tbs = new ArrayBuffer(0); // Value of TBS part before decode + + // OPTIONAL this.version = 0; + // OPTIONAL this.requestorName = new in_window.org.pkijs.simpl.GENERAL_NAME(); + this.requestList = new Array(); // Array of "Request" objects + // OPTIONAL this.requestExtensions = new Array(); // Array of in_window.org.pkijs.simpl.EXTENSION(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.ocsp.TBSRequest.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.tbs = arguments[0].tbs || new ArrayBuffer(0); // Value of TBS part before decode + + if("version" in arguments[0]) + this.version = arguments[0].version; + if("requestorName" in arguments[0]) + this.requestorName = arguments[0].requestorName; + this.requestList = arguments[0].requestList || new Array(); // Array of "Request" objects + if("requestExtensions" in arguments[0]) + this.requestExtensions = arguments[0].requestExtensions; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.TBSRequest.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.ocsp.TBSRequest() + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for TBSRequest"); + // #endregion + + // #region Get internal properties from parsed schema + this.tbs = asn1.result["TBSRequest"].value_before_decode; + + if("TBSRequest.version" in asn1.result) + this.version = asn1.result["TBSRequest.version"].value_block.value_dec; + if("TBSRequest.requestorName" in asn1.result) + this.requestorName = new in_window.org.pkijs.simpl.GENERAL_NAME({ schema: asn1.result["TBSRequest.requestorName"] }); + + var requests = asn1.result["TBSRequest.requests"]; + for(var i = 0; i < requests.length; i++) + this.requestList.push(new in_window.org.pkijs.simpl.ocsp.Request({ schema: requests[i] })); + + if("TBSRequest.requestExtensions" in asn1.result) + { + this.requestExtensions = new Array(); + var exts = asn1.result["TBSRequest.requestExtensions"].value_block.value; + + for(var i = 0; i < exts.length; i++) + this.requestExtensions.push(new in_window.org.pkijs.simpl.EXTENSION({ schema: exts[i] })); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.TBSRequest.prototype.toSchema = + function(encodeFlag) + { + /// If param equal to false then create TBS schema via decoding stored value. In othe case create TBS schema via assembling from TBS parts. + + // #region Check "encodeFlag" + if(typeof encodeFlag === "undefined") + encodeFlag = false; + // #endregion + + // #region Decode stored TBS value + var tbs_schema; + + if(encodeFlag === false) + { + if(this.tbs.byteLength === 0) // No stored TBS part + return in_window.org.pkijs.schema.ocsp.TBSRequest(); + + tbs_schema = in_window.org.pkijs.fromBER(this.tbs).result; + } + // #endregion + // #region Create TBS schema via assembling from TBS parts + else + { + var output_array = new Array(); + + if("version" in this) + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [new in_window.org.pkijs.asn1.INTEGER({ value: this.version })] + })); + + if("requestorName" in this) + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [this.requestorName.toSchema()] + })); + + var requests = new Array(); + + for(var i = 0; i < this.requestList.length; i++) + requests.push(this.requestList[i].toSchema()); + + output_array.push(new in_window.org.pkijs.asn1.SEQUENCE({ + value: requests + })); + + if("requestExtensions" in this) + { + var extensions = new Array(); + + for(var j = 0; j < this.requestExtensions.length; j++) + extensions.push(this.requestExtensions[j].toSchema()); + + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 2 // [2] + }, + value: [ + new in_window.org.pkijs.asn1.SEQUENCE({ + value: extensions + }) + ] + })); + } + + tbs_schema = new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + }); + } + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return tbs_schema; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.TBSRequest.prototype.toJSON = + function() + { + var _object = {}; + + if("version" in this) + _object.version = this.version; + + if("requestorName" in this) + _object.requestorName = this.requestorName.toJSON(); + + _object.requestList = new Array(); + + for(var i = 0; i < this.requestList.length; i++) + _object.requestList.push(this.requestList[i].toJSON()); + + if("requestExtensions" in this) + { + _object.requestExtensions = new Array(); + + for(var i = 0; i < this.requestExtensions.length; i++) + _object.requestExtensions.push(this.requestExtensions[i].toJSON()); + } + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "Signature" type + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.Signature = + function() + { + // #region Internal properties of the object + this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.signature = new in_window.org.pkijs.asn1.BITSTRING(); + // OPTIONAL this.certs = new Array(); // Array of X.509 certificates + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.ocsp.Signature.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.signatureAlgorithm = arguments[0].signatureAlgorithm || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.signature = arguments[0].signature || new in_window.org.pkijs.asn1.BITSTRING(); + if("certs" in arguments[0]) + this.certs = arguments[0].certs; // Array of X.509 certificates + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.Signature.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.ocsp.Signature({ + names: { + signatureAlgorithm: { + names: { + block_name: "signatureAlgorithm" + } + }, + signature: "signature", + certs: "certs" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for ocsp.Signature"); + // #endregion + + // #region Get internal properties from parsed schema + this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["signatureAlgorithm"] }); + this.signature = asn1.result["signature"]; + if("certs" in asn1.result) + { + this.certs = new Array(); + + var certs_array = asn1.result["certs"]; + for(var i = 0; i < certs_array; i++) + this.certs.push(new in_window.org.pkijs.simpl.CERT({ schema: certs_array[i] })); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.Signature.prototype.toSchema = + function() + { + // #region Create array of output sequence + var output_array = new Array(); + + output_array.push(this.signatureAlgorithm.toSchema()); + output_array.push(this.signature); + if("certs" in this) + { + // #region Create certificate array + var cert_array = new Array(); + + for(var i = 0; i < this.certs.length; i++) + cert_array.push(this.certs[i].toSchema()); + // #endregion + + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [ + new in_window.org.pkijs.asn1.SEQUENCE({ + value: cert_array + }) + ] + })); + } + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.Signature.prototype.toJSON = + function() + { + var _object = { + signatureAlgorithm: this.signatureAlgorithm.toJSON(), + signature: this.signature.toJSON() + }; + + if("certs" in this) + { + _object.certs = new Array(); + + for(var i = 0; i < this.certs.length; i++) + _object.certs.push(this.certs[i].toJSON()); + } + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "OCSP_REQUEST" type + //************************************************************************************** + in_window.org.pkijs.simpl.OCSP_REQUEST = + function() + { + // #region Internal properties of the object + this.tbsRequest = new in_window.org.pkijs.simpl.ocsp.TBSRequest(); + // OPTIONAL this.optionalSignature = new in_window.org.pkijs.simpl.ocsp.Signature(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.OCSP_REQUEST.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.tbsRequest = arguments[0].tbsRequest || new in_window.org.pkijs.simpl.ocsp.TBSRequest(); + if("optionalSignature" in arguments[0]) + this.optionalSignature = arguments[0].optionalSignature; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.OCSP_REQUEST.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.OCSP_REQUEST() + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for OCSP_REQUEST"); + // #endregion + + // #region Get internal properties from parsed schema + this.tbsRequest = new in_window.org.pkijs.simpl.ocsp.TBSRequest({ schema: asn1.result["tbsRequest"] }); + if("optionalSignature" in asn1.result) + this.optionalSignature = new in_window.org.pkijs.simpl.ocsp.Signature({ schema: asn1.result["optionalSignature"] }); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.OCSP_REQUEST.prototype.toSchema = + function(encodeFlag) + { + /// If param equal to false then create TBS schema via decoding stored value. In othe case create TBS schema via assembling from TBS parts. + + // #region Check "encodeFlag" + if(typeof encodeFlag === "undefined") + encodeFlag = false; + // #endregion + + // #region Create array for output sequence + var output_array = new Array(); + + output_array.push(this.tbsRequest.toSchema(encodeFlag)); + if("optionalSignature" in this) + output_array.push(this.optionalSignature.toSchema()); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.OCSP_REQUEST.prototype.sign = + function(privateKey, hashAlgorithm) + { + /// Private key for "subjectPublicKeyInfo" structure + /// Hashing algorithm. Default SHA-1 + + // #region Initial variables + var _this = this; + // #endregion + + // #region Get a private key from function parameter + if(typeof privateKey === "undefined") + return Promise.reject("Need to provide a private key for signing"); + // #endregion + + // #region Get hashing algorithm + if(typeof hashAlgorithm === "undefined") + hashAlgorithm = "SHA-1"; + else + { + // #region Simple check for supported algorithm + var oid = in_window.org.pkijs.getOIDByAlgorithm({ name: hashAlgorithm }); + if(oid === "") + return Promise.reject("Unsupported hash algorithm: " + hashAlgorithm); + // #endregion + } + // #endregion + + // #region Check that "optionalSignature" exists in the current request + if(("optionalSignature" in this) === false) + return Promise.reject("Need to create \"optionalSignature\" field before signing"); + // #endregion + + // #region Get a "default parameters" for current algorithm + var defParams = in_window.org.pkijs.getAlgorithmParameters(privateKey.algorithm.name, "sign"); + defParams.algorithm.hash.name = hashAlgorithm; + // #endregion + + // #region Fill internal structures base on "privateKey" and "hashAlgorithm" + switch(privateKey.algorithm.name.toUpperCase()) + { + case "RSASSA-PKCS1-V1_5": + case "ECDSA": + _this.optionalSignature.signatureAlgorithm.algorithm_id = in_window.org.pkijs.getOIDByAlgorithm(defParams.algorithm); + break; + case "RSA-PSS": + { + // #region Set "saltLength" as a length (in octets) of hash function result + switch(hashAlgorithm.toUpperCase()) + { + case "SHA-256": + defParams.algorithm.saltLength = 32; + break; + case "SHA-384": + defParams.algorithm.saltLength = 48; + break; + case "SHA-512": + defParams.algorithm.saltLength = 64; + break; + default:; + } + // #endregion + + // #region Fill "RSASSA_PSS_params" object + var paramsObject = {}; + + if(hashAlgorithm.toUpperCase() !== "SHA-1") + { + var hashAlgorithmOID = in_window.org.pkijs.getOIDByAlgorithm({ name: hashAlgorithm }); + if(hashAlgorithmOID === "") + return Promise.reject("Unsupported hash algorithm: " + hashAlgorithm); + + paramsObject.hashAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: hashAlgorithmOID, + algorithm_params: new in_window.org.pkijs.asn1.NULL() + }); + + paramsObject.maskGenAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: "1.2.840.113549.1.1.8", // MGF1 + algorithm_params: paramsObject.hashAlgorithm.toSchema() + }) + } + + if(defParams.algorithm.saltLength !== 20) + paramsObject.saltLength = defParams.algorithm.saltLength; + + var pssParameters = new in_window.org.pkijs.simpl.x509.RSASSA_PSS_params(paramsObject); + // #endregion + + // #region Automatically set signature algorithm + _this.optionalSignature.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: "1.2.840.113549.1.1.10", + algorithm_params: pssParameters.toSchema() + }); + // #endregion + } + break; + default: + return Promise.reject("Unsupported signature algorithm: " + privateKey.algorithm.name); + } + // #endregion + + // #region Create TBS data for signing + var tbs = this.tbsRequest.toSchema(true).toBER(false); + // #endregion + + // #region Get a "crypto" extension + var crypto = in_window.org.pkijs.getCrypto(); + if(typeof crypto == "undefined") + return Promise.reject("Unable to create WebCrypto object"); + // #endregion + + // #region Signing TBS data on provided private key + return crypto.sign(defParams.algorithm, + privateKey, + new Uint8Array(tbs)).then( + function(result) + { + // #region Special case for ECDSA algorithm + if(defParams.algorithm.name === "ECDSA") + result = in_window.org.pkijs.createCMSECDSASignature(result); + // #endregion + + _this.optionalSignature.signature = new in_window.org.pkijs.asn1.BITSTRING({ value_hex: result }); + }, + function(error) + { + return Promise.reject("Signing error: " + error); + } + ); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.OCSP_REQUEST.prototype.toJSON = + function() + { + var _object = { + tbsRequest: this.tbsRequest.toJSON() + }; + + if("optionalSignature" in this) + _object.optionalSignature = this.optionalSignature.toJSON(); + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.OCSP_REQUEST.prototype.createForCertificate = + function(certificate, parameters) + { + /// Making OCSP Request for specific certificate + /// Certificate making OCSP Request for + /// Additional parameters + + // #region Initial variables + var _this = this; + var sequence = Promise.resolve(); + + var certID = new in_window.org.pkijs.simpl.ocsp.CertID(); + // #endregion + + // #region Create OCSP certificate identifier for the certificate + sequence = sequence.then( + function(result) + { + return certID.createForCertificate(certificate, parameters); + } + ); + // #endregion + + // #region Make final request data + sequence = sequence.then( + function(result) + { + _this.tbsRequest = new in_window.org.pkijs.simpl.ocsp.TBSRequest({ + requestList: [ + new in_window.org.pkijs.simpl.ocsp.Request({ + reqCert: certID + }) + ] + }) + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + return sequence; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "ResponseBytes" type + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.ResponseBytes = + function() + { + // #region Internal properties of the object + this.responseType = ""; + this.response = new in_window.org.pkijs.asn1.OCTETSTRING(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.ocsp.ResponseBytes.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.responseType = arguments[0].responseType || ""; + this.response = arguments[0].response || new in_window.org.pkijs.asn1.OCTETSTRING(); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.ResponseBytes.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.ocsp.ResponseBytes({ + names: { + responseType: "responseType", + response: "response" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for ResponseBytes"); + // #endregion + + // #region Get internal properties from parsed schema + this.responseType = asn1.result["responseType"].value_block.toString(); + this.response = asn1.result["response"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.ResponseBytes.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + new in_window.org.pkijs.asn1.OID({ value: this.responseType }), + this.response + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.ResponseBytes.prototype.toJSON = + function() + { + return { + responseType: this.responseType, + response: this.response.toJSON() + }; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "OCSP_RESPONSE" type + //************************************************************************************** + in_window.org.pkijs.simpl.OCSP_RESPONSE = + function() + { + // #region Internal properties of the object + this.responseStatus = new in_window.org.pkijs.asn1.ENUMERATED(); + // OPTIONAL this.responseBytes = new in_window.org.pkijs.simpl.ocsp.ResponseBytes(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.OCSP_RESPONSE.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.responseStatus = arguments[0].responseStatus || new in_window.org.pkijs.asn1.ENUMERATED(); + if("responseBytes" in arguments[0]) + this.responseBytes = arguments[0].responseBytes; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.OCSP_RESPONSE.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.OCSP_RESPONSE() + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for OCSP_RESPONSE"); + // #endregion + + // #region Get internal properties from parsed schema + this.responseStatus = asn1.result["responseStatus"]; + if("responseBytes" in asn1.result) + this.responseBytes = new in_window.org.pkijs.simpl.ocsp.ResponseBytes({ schema: asn1.result["responseBytes"] }); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.OCSP_RESPONSE.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + output_array.push(this.responseStatus); + if("responseBytes" in this) + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [this.responseBytes.toSchema()] + })); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.OCSP_RESPONSE.prototype.verify = + function() + { + /// !!! Works well in Chrome dev versions only (April 2014th) !!! + /// Returns a new Promise object (in case of error), or a result of "crypto.subtle.veryfy" function + + var _this = this; + + // #region Check that ResponseBytes exists in the object + if(("responseBytes" in this) === false) + return Promise.reject("Empty ResponseBytes field"); + // #endregion + + // #region Check that ResponceData has type BasicOCSPResponse and verify it + if(this.responseBytes.responseType === "1.3.6.1.5.5.7.48.1.1") + { + var asn1 = in_window.org.pkijs.fromBER(this.responseBytes.response.value_block.value_hex); + var basic_resp_simpl = new in_window.org.pkijs.simpl.OCSP_BASIC_RESPONSE({ schema: asn1.result }); + + return basic_resp_simpl.verify(); + } + else + return Promise.reject("Unknown ResponseBytes type: " + _this.responseBytes.responseType); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.OCSP_RESPONSE.prototype.sign = + function(privateKey, hashAlgorithm) + { + /// Private key for "subjectPublicKeyInfo" structure + /// Hashing algorithm. Default SHA-1 + + var _this = this; + + // #region Check that ResponceData has type BasicOCSPResponse and verify it + if(this.responseBytes.responseType === "1.3.6.1.5.5.7.48.1.1") + { + var asn1 = in_window.org.pkijs.fromBER(this.responseBytes.response.value_block.value_hex); + var basic_resp_simpl = new in_window.org.pkijs.simpl.OCSP_BASIC_RESPONSE({ schema: asn1.result }); + + return basic_resp_simpl.sign(privateKey, hashAlgorithm); + } + else + return Promise.reject("Unknown ResponseBytes type: " + _this.responseBytes.responseType); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.OCSP_RESPONSE.prototype.toJSON = + function() + { + var _object = { + responseStatus: this.responseStatus.toJSON() + }; + + if("responseBytes" in this) + _object.responseBytes = this.responseBytes.toJSON(); + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.OCSP_RESPONSE.prototype.getCertificateStatus = + function(certificate, issuerCertificate) + { + /// Get OCSP response status for specific certificate + /// Identifier of the certificate to be checked + + // #region Initial variables + var basicResponse; + + var result = { + isForCertificate: false, + status: 2 // 0 = good, 1 = revoked, 2 = unknown + }; + // #endregion + + // #region Check that "ResponseBytes" contain "OCSP_BASIC_RESPONSE" + if(("responseBytes" in this) == false) + return result; + + if(this.responseBytes.responseType != "1.3.6.1.5.5.7.48.1.1") // id-pkix-ocsp-basic + return result; + + try + { + var asn1Basic = in_window.org.pkijs.fromBER(this.responseBytes.response.value_block.value_hex); + basicResponse = new in_window.org.pkijs.simpl.OCSP_BASIC_RESPONSE({ schema: asn1Basic.result }); + } + catch(ex) + { + return result; + } + // #endregion + + return basicResponse.getCertificateStatus(certificate, issuerCertificate); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "SingleResponse" type + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.SingleResponse = + function() + { + // #region Internal properties of the object + this.certID = new in_window.org.pkijs.simpl.ocsp.CertID(); + this.certStatus = new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 3 // [3] + }, + value: [] + }); // Fiction value + this.thisUpdate = new Date(0, 0, 0); + // OPTIONAL this.nextUpdate = new Date(0, 0, 0); + // OPTIONAL this.singleExtensions = new Array(); // Array of in_window.org.pkijs.simpl.EXTENSION(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.ocsp.SingleResponse.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.certID = arguments[0].certID || new in_window.org.pkijs.simpl.ocsp.CertID(); + this.certStatus = arguments[0].certStatus || new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 3 // [3] + }, + value: [] + }); // Fiction value + this.thisUpdate = arguments[0].thisUpdate || new Date(0, 0, 0); + if("nextUpdate" in arguments[0]) + this.nextUpdate = arguments[0].nextUpdate; + if("singleExtensions" in arguments[0]) + this.singleExtensions = arguments[0].singleExtensions; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.SingleResponse.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.ocsp.SingleResponse({ + names: { + certID: { + names: { + block_name: "certID" + } + }, + certStatus: "certStatus", + thisUpdate: "thisUpdate", + nextUpdate: "nextUpdate", + singleExtensions: "singleExtensions" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for SingleResponse"); + // #endregion + + // #region Get internal properties from parsed schema + this.certID = new in_window.org.pkijs.simpl.ocsp.CertID({ schema: asn1.result["certID"] }); + this.certStatus = asn1.result["certStatus"]; + this.thisUpdate = asn1.result["thisUpdate"].toDate(); + if("nextUpdate" in asn1.result) + this.nextUpdate = asn1.result["nextUpdate"].toDate(); + + if("singleExtensions" in asn1.result) + { + this.singleExtensions = new Array(); + var exts = asn1.result["singleExtensions"].value_block.value; + + for(var i = 0; i < exts.length; i++) + this.singleExtensions.push(new in_window.org.pkijs.simpl.EXTENSION({ schema: exts[i] })); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.SingleResponse.prototype.toSchema = + function() + { + // #region Create value array for output sequence + var output_array = new Array(); + + output_array.push(this.certID.toSchema()); + output_array.push(this.certStatus); + output_array.push(new in_window.org.pkijs.asn1.GENERALIZEDTIME({ value_date: this.thisUpdate })); + if("nextUpdate" in this) + output_array.push(new in_window.org.pkijs.asn1.GENERALIZEDTIME({ value_date: this.nextUpdate })); + + if("singleExtensions" in this) + { + var extensions = new Array(); + + for(var j = 0; j < this.singleExtensions.length; j++) + extensions.push(this.singleExtensions[j].toSchema()); + + output_array.push(new in_window.org.pkijs.asn1.SEQUENCE({ + value: extensions + })); + } + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.SingleResponse.prototype.toJSON = + function() + { + var _object = { + certID: this.certID.toJSON(), + certStatus: this.certStatus.toJSON(), + thisUpdate: this.thisUpdate + }; + + if("nextUpdate" in this) + _object.nextUpdate = this.nextUpdate; + + if("singleExtensions" in this) + { + _object.singleExtensions = new Array(); + + for(var i = 0; i < this.singleExtensions.length; i++) + _object.singleExtensions.push(this.singleExtensions[i].toJSON()); + } + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "ResponseData" type + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.ResponseData = + function() + { + // #region Internal properties of the object + this.tbs = new ArrayBuffer(0); + + // OPTIONAL this.version = 0; + this.responderID = new in_window.org.pkijs.simpl.RDN(); // Fake value + this.producedAt = new Date(0, 0, 0); + this.responses = new Array(); // Array of "SingleResponse" objects + // OPTIONAL this.responseExtensions = new Array(); // Array of in_window.org.pkijs.simpl.EXTENSION(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.ocsp.ResponseData.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + if("version" in arguments[0]) + this.version = arguments[0].version; + this.responderID = arguments[0].responderID || new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 10 // [10] + }, + value: [] + }); // Fake value + this.producedAt = arguments[0].producedAt || new Date(0, 0, 0); + this.responses = arguments[0].responses || new Array(); // Array of "SingleResponse" objects + if("responseExtensions" in arguments[0]) + this.responseExtensions = arguments[0].responseExtensions; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.ResponseData.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.ocsp.ResponseData() + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for ocsp.ResponseData"); + // #endregion + + // #region Get internal properties from parsed schema + this.tbs = asn1.result["ResponseData"].value_before_decode; + + if("ResponseData.version" in asn1.result) + this.version = asn1.result["ResponseData.version"].value_block.value_dec; + + if(asn1.result["ResponseData.responderID"].id_block.tag_number === 1) + this.responderID = new in_window.org.pkijs.simpl.RDN({ schema: asn1.result["ResponseData.responderID"].value_block.value[0] }); + else + this.responderID = asn1.result["ResponseData.responderID"].value_block.value[0]; // OCTETSTRING + + this.producedAt = asn1.result["ResponseData.producedAt"].toDate(); + + var responses_array = asn1.result["ResponseData.responses"]; + for(var i = 0; i < responses_array.length; i++) + this.responses.push(new in_window.org.pkijs.simpl.ocsp.SingleResponse({ schema: responses_array[i] })); + + if("ResponseData.responseExtensions" in asn1.result) + { + this.responseExtensions = new Array(); + var exts = asn1.result["ResponseData.responseExtensions"].value_block.value; + + for(var i = 0; i < exts.length; i++) + this.responseExtensions.push(new in_window.org.pkijs.simpl.EXTENSION({ schema: exts[i] })); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.ResponseData.prototype.toSchema = + function(encodeFlag) + { + /// If param equal to false then create TBS schema via decoding stored value. In othe case create TBS schema via assembling from TBS parts. + + // #region Check "encodeFlag" + if(typeof encodeFlag === "undefined") + encodeFlag = false; + // #endregion + + // #region Decode stored TBS value + var tbs_schema; + + if(encodeFlag === false) + { + if(this.tbs.length === 0) // No stored certificate TBS part + return in_window.org.pkijs.schema.ocsp.ResponseData(); + + tbs_schema = in_window.org.pkijs.fromBER(this.tbs).result; + } + // #endregion + // #region Create TBS schema via assembling from TBS parts + else + { + var output_array = new Array(); + + if("version" in this) + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [new in_window.org.pkijs.asn1.INTEGER({ value: this.version })] + })); + + if(this.responderID instanceof in_window.org.pkijs.simpl.RDN) + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [this.responderID.toSchema()] + })); + else + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 2 // [2] + }, + value: [this.responderID] + })); + + output_array.push(new in_window.org.pkijs.asn1.GENERALIZEDTIME({ value_date: this.producedAt })); + + var responses = new Array(); + + for(var i = 0; i < this.responses.length; i++) + responses.push(this.responses[i].toSchema()); + + output_array.push(new in_window.org.pkijs.asn1.SEQUENCE({ + value: responses + })); + + if("responseExtensions" in this) + { + var extensions = new Array(); + + for(var j = 0; j < this.responseExtensions.length; j++) + extensions.push(this.responseExtensions[j].toSchema()); + + output_array.push(new in_window.org.pkijs.asn1.SEQUENCE({ + value: extensions + })); + } + + tbs_schema = new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + }); + } + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return tbs_schema; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ocsp.ResponseData.prototype.toJSON = + function() + { + var _object = {}; + + if("version" in this) + _object.version = this.version; + + if("responderID" in this) + _object.responderID = this.responderID; + + if("producedAt" in this) + _object.producedAt = this.producedAt; + + if("responses" in this) + { + _object.responses = new Array(); + + for(var i = 0; i < this.responses.length; i++) + _object.responses.push(this.responses[i].toJSON()); + } + + if("responseExtensions" in this) + { + _object.responseExtensions = new Array(); + + for(var i = 0; i < this.responseExtensions.length; i++) + _object.responseExtensions.push(this.responseExtensions[i].toJSON()); + } + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "OCSP_BASIC_RESPONSE" type + //************************************************************************************** + in_window.org.pkijs.simpl.OCSP_BASIC_RESPONSE = + function() + { + // #region Internal properties of the object + this.tbsResponseData = new in_window.org.pkijs.simpl.ocsp.ResponseData(); + this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.signature = new in_window.org.pkijs.asn1.BITSTRING(); + // OPTIONAL this.certs = new Array(); // Array of in_window.org.pkijs.simpl.CERT + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.OCSP_BASIC_RESPONSE.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.tbsResponseData = arguments[0].tbsResponseData || new in_window.org.pkijs.simpl.ocsp.ResponseData(); + this.signatureAlgorithm = arguments[0].signatureAlgorithm || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.signature = arguments[0].signature || new in_window.org.pkijs.asn1.BITSTRING(); + if("certs" in arguments[0]) + this.certs = arguments[0].certs; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.OCSP_BASIC_RESPONSE.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.OCSP_BASIC_RESPONSE() + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for OCSP_BASIC_RESPONSE"); + // #endregion + + // #region Get internal properties from parsed schema + this.tbsResponseData = new in_window.org.pkijs.simpl.ocsp.ResponseData({ schema: asn1.result["BasicOCSPResponse.tbsResponseData"] }); + this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["BasicOCSPResponse.signatureAlgorithm"] }); + this.signature = asn1.result["BasicOCSPResponse.signature"]; + + if("BasicOCSPResponse.certs" in asn1.result) + { + this.certs = new Array(); + + var certs_array = asn1.result["BasicOCSPResponse.certs"]; + + for(var i = 0; i < certs_array.length; i++) + this.certs.push(new in_window.org.pkijs.simpl.CERT({ schema: certs_array[i] })); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.OCSP_BASIC_RESPONSE.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + output_array.push(this.tbsResponseData.toSchema()); + output_array.push(this.signatureAlgorithm.toSchema()); + output_array.push(this.signature); + + // #region Create array of certificates + if("certs" in this) + { + var certs_array = new Array(); + + for(var i = 0; i < this.certs.length; i++) + certs_array.push(this.certs[i].toSchema()); + + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [ + new in_window.org.pkijs.asn1.SEQUENCE({ + value: certs_array + }) + ] + })); + } + // #endregion + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.OCSP_BASIC_RESPONSE.prototype.verify = + function() + { + /// !!! Works well in Chrome dev versions only (April 2014th) !!! + /// Returns a new Promise object (in case of error), or a result of "crypto.subtle.veryfy" function + + // #region Check amount of certificates + if(("certs" in this) === false) + return Promise.reject("No certificates attached to the BasicOCSPResponce"); + // #endregion + + // #region Global variables (used in "promises") + var _this = this; + + var signer_cert = null; + + var certs = this.certs; + var signature_view = new Uint8Array(this.signature.value_block.value_hex); + var tbs_view = new Uint8Array(this.tbsResponseData.tbs); + + var cert_index = -1; + + var sequence = Promise.resolve(); + + var sha_algorithm = ""; + + var trusted_certs = new Array(); + // #endregion + + // #region Get input values + if(arguments[0] instanceof Object) + { + if("trusted_certs" in arguments[0]) + trusted_certs = arguments[0].trusted_certs; + } + // #endregion + + // #region Get a "crypto" extension + var crypto = in_window.org.pkijs.getCrypto(); + if(typeof crypto == "undefined") + return Promise.reject("Unable to create WebCrypto object"); + // #endregion + + // #region Find a correct hashing algorithm + sha_algorithm = in_window.org.pkijs.getHashAlgorithm(this.signatureAlgorithm); + if(sha_algorithm === "") + return Promise.reject("Unsupported signature algorithm: " + _this.signatureAlgorithm.algorithm_id); + // #endregion + + // #region Find correct value for "responderID" + var responder_type = 0; + var responder_id = {}; + + if(this.tbsResponseData.responderID instanceof in_window.org.pkijs.simpl.RDN) // [1] Name + { + responder_type = 0; + responder_id = this.tbsResponseData.responderID; + } + else + { + if(this.tbsResponseData.responderID instanceof in_window.org.pkijs.asn1.OCTETSTRING) // [2] KeyHash + { + responder_type = 1; + responder_id = this.tbsResponseData.responderID; + } + else + return Promise.reject("Wrong value for responderID"); + } + // #endregion + + // #region Compare responderID with all certificates one-by-one + if(responder_type === 0) // By Name + { + sequence = sequence.then( + function() + { + for(var i = 0; i < certs.length; i++) + { + if(certs[i].subject.isEqual(responder_id)) + { + cert_index = i; + break; + } + } + } + ); + } + else // By KeyHash + { + sequence = sequence.then( + function() + { + var digest_promises = new Array(); + + for(var i = 0; i < certs.length; i++) + digest_promises.push(crypto.digest({ name: "sha-1" }, new Uint8Array(certs[i].subjectPublicKeyInfo.subjectPublicKey.value_block.value_hex))); + + return Promise.all(digest_promises).then( + function(results) + { + for(var i = 0; i < certs.length; i++) + { + if(in_window.org.pkijs.isEqual_buffer(results[i], responder_id.value_block.value_hex)) + { + cert_index = i; + break; + } + } + } + ); + } + ); + } + // #endregion + + // #region Make additional verification for signer's certificate + function checkCA(cert) + { + /// Certificate to find CA flag for + + // #region Do not include signer's certificate + if((cert.issuer.isEqual(signer_cert.issuer) === true) && (cert.serialNumber.isEqual(signer_cert.serialNumber) === true)) + return null; + // #endregion + + var isCA = false; + + for(var i = 0; i < cert.extensions.length; i++) + { + if(cert.extensions[i].extnID === "2.5.29.19") // BasicConstraints + { + if("cA" in cert.extensions[i].parsedValue) + { + if(cert.extensions[i].parsedValue.cA === true) + isCA = true; + } + } + } + + if(isCA) + return cert; + else + return null; + } + + var checkCA_promises = new Array(); + + sequence = sequence.then( + function(result) + { + if(cert_index === (-1)) + return Promise.reject("Correct certificate was not found in OCSP response"); + + signer_cert = certs[cert_index]; + + for(var i = 0; i < _this.certs.length; i++) + checkCA_promises.push(checkCA(_this.certs[i])); + + return Promise.all(checkCA_promises).then( + function(promiseResults) + { + var additional_certs = new Array(); + additional_certs.push(signer_cert); + + for(var i = 0; i < promiseResults.length; i++) + { + if(promiseResults[i] !== null) + additional_certs.push(promiseResults[i]); + } + + var cert_chain_simpl = new in_window.org.pkijs.simpl.CERT_CHAIN({ + certs: additional_certs, + trusted_certs: trusted_certs + }); + if("crls" in _this) + cert_chain_simpl.crls = _this.crls; + + return cert_chain_simpl.verify().then( + function(result) + { + if(result.result === true) + return Promise.resolve(); + else + return Promise.reject("Validation of signer's certificate failed"); + }, + function(error) + { + return Promise.reject("Validation of signer's certificate failed with error: " + ((error instanceof Object) ? error.result_message : error)); + } + ); + }, + function(promiseError) + { + return Promise.reject("Error during checking certificates for CA flag: " + promiseError); + } + ); + } + ); + // #endregion + + // #region Import public key from responder certificate + sequence = sequence.then( + function() + { + // #region Get information about public key algorithm and default parameters for import + var algorithmObject = in_window.org.pkijs.getAlgorithmByOID(certs[cert_index].signatureAlgorithm.algorithm_id); + if(("name" in algorithmObject) === false) + return Promise.reject("Unsupported public key algorithm: " + certs[cert_index].signatureAlgorithm.algorithm_id); + + var algorithm_name = algorithmObject.name; + + var algorithm = in_window.org.pkijs.getAlgorithmParameters(algorithm_name, "importkey"); + if("hash" in algorithm.algorithm) + algorithm.algorithm.hash.name = sha_algorithm; + + // #region Special case for ECDSA + if(algorithm_name === "ECDSA") + { + // #region Get information about named curve + if((certs[cert_index].subjectPublicKeyInfo.algorithm.algorithm_params instanceof in_window.org.pkijs.asn1.OID) === false) + return Promise.reject("Incorrect type for ECDSA public key parameters"); + + var curveObject = in_window.org.pkijs.getAlgorithmByOID(certs[cert_index].subjectPublicKeyInfo.algorithm.algorithm_params.value_block.toString()); + if(("name" in curveObject) === false) + return Promise.reject("Unsupported named curve algorithm: " + certs[cert_index].subjectPublicKeyInfo.algorithm.algorithm_params.value_block.toString()); + // #endregion + + algorithm.algorithm.namedCurve = curveObject.name; + } + // #endregion + // #endregion + + var publicKeyInfo_schema = certs[cert_index].subjectPublicKeyInfo.toSchema(); + var publicKeyInfo_buffer = publicKeyInfo_schema.toBER(false); + var publicKeyInfo_view = new Uint8Array(publicKeyInfo_buffer); + + return crypto.importKey("spki", publicKeyInfo_view, algorithm.algorithm, true, algorithm.usages); + } + ); + // #endregion + + // #region Verifying TBS part of BasicOCSPResponce + sequence = sequence.then( + function(publicKey) + { + // #region Get default algorithm parameters for verification + var algorithm = in_window.org.pkijs.getAlgorithmParameters(publicKey.algorithm.name, "verify"); + if("hash" in algorithm.algorithm) + algorithm.algorithm.hash.name = sha_algorithm; + // #endregion + + // #region Special case for ECDSA signatures + var signature_value = _this.signature.value_block.value_hex; + + if(publicKey.algorithm.name === "ECDSA") + { + var asn1 = in_window.org.pkijs.fromBER(signature_value); + signature_value = in_window.org.pkijs.createECDSASignatureFromCMS(asn1.result); + } + // #endregion + + // #region Special case for RSA-PSS + if(publicKey.algorithm.name === "RSA-PSS") + { + var pssParameters; + + try + { + pssParameters = new in_window.org.pkijs.simpl.x509.RSASSA_PSS_params({ schema: _this.signatureAlgorithm.algorithm_params }); + } + catch(ex) + { + return Promise.reject(ex); + } + + if("saltLength" in pssParameters) + algorithm.algorithm.saltLength = pssParameters.saltLength; + else + algorithm.algorithm.saltLength = 20; + + var hash_algo = "SHA-1"; + + if("hashAlgorithm" in pssParameters) + { + var hashAlgorithm = in_window.org.pkijs.getAlgorithmByOID(pssParameters.hashAlgorithm.algorithm_id); + if(("name" in hashAlgorithm) === false) + return Promise.reject("Unrecognized hash algorithm: " + pssParameters.hashAlgorithm.algorithm_id); + + hash_algo = hashAlgorithm.name; + } + + algorithm.algorithm.hash.name = hash_algo; + } + // #endregion + + return crypto.verify(algorithm.algorithm, + publicKey, + new Uint8Array(signature_value), + tbs_view); + } + ); + // #endregion + + return sequence; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.OCSP_BASIC_RESPONSE.prototype.sign = + function(privateKey, hashAlgorithm) + { + /// Private key for "subjectPublicKeyInfo" structure + /// Hashing algorithm. Default SHA-1 + + // #region Initial variables + var _this = this; + // #endregion + + // #region Get a private key from function parameter + if(typeof privateKey === "undefined") + return Promise.reject("Need to provide a private key for signing"); + // #endregion + + // #region Get hashing algorithm + if(typeof hashAlgorithm === "undefined") + hashAlgorithm = "SHA-1"; + else + { + // #region Simple check for supported algorithm + var oid = in_window.org.pkijs.getOIDByAlgorithm({ name: hashAlgorithm }); + if(oid === "") + return Promise.reject("Unsupported hash algorithm: " + hashAlgorithm); + // #endregion + } + // #endregion + + // #region Get a "default parameters" for current algorithm + var defParams = in_window.org.pkijs.getAlgorithmParameters(privateKey.algorithm.name, "sign"); + defParams.algorithm.hash.name = hashAlgorithm; + // #endregion + + // #region Fill internal structures base on "privateKey" and "hashAlgorithm" + switch(privateKey.algorithm.name.toUpperCase()) + { + case "RSASSA-PKCS1-V1_5": + case "ECDSA": + _this.signatureAlgorithm.algorithm_id = in_window.org.pkijs.getOIDByAlgorithm(defParams.algorithm); + break; + case "RSA-PSS": + { + // #region Set "saltLength" as a length (in octets) of hash function result + switch(hashAlgorithm.toUpperCase()) + { + case "SHA-256": + defParams.algorithm.saltLength = 32; + break; + case "SHA-384": + defParams.algorithm.saltLength = 48; + break; + case "SHA-512": + defParams.algorithm.saltLength = 64; + break; + default:; + } + // #endregion + + // #region Fill "RSASSA_PSS_params" object + var paramsObject = {}; + + if(hashAlgorithm.toUpperCase() !== "SHA-1") + { + var hashAlgorithmOID = in_window.org.pkijs.getOIDByAlgorithm({ name: hashAlgorithm }); + if(hashAlgorithmOID === "") + return Promise.reject("Unsupported hash algorithm: " + hashAlgorithm); + + paramsObject.hashAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: hashAlgorithmOID, + algorithm_params: new in_window.org.pkijs.asn1.NULL() + }); + + paramsObject.maskGenAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: "1.2.840.113549.1.1.8", // MGF1 + algorithm_params: paramsObject.hashAlgorithm.toSchema() + }) + } + + if(defParams.algorithm.saltLength !== 20) + paramsObject.saltLength = defParams.algorithm.saltLength; + + var pssParameters = new in_window.org.pkijs.simpl.x509.RSASSA_PSS_params(paramsObject); + // #endregion + + // #region Automatically set signature algorithm + _this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: "1.2.840.113549.1.1.10", + algorithm_params: pssParameters.toSchema() + }); + // #endregion + } + break; + default: + return Promise.reject("Unsupported signature algorithm: " + privateKey.algorithm.name); + } + // #endregion + + // #region Create TBS data for signing + _this.tbsResponseData.tbs = _this.tbsResponseData.toSchema(true).toBER(false); + // #endregion + + // #region Get a "crypto" extension + var crypto = in_window.org.pkijs.getCrypto(); + if(typeof crypto == "undefined") + return Promise.reject("Unable to create WebCrypto object"); + // #endregion + + // #region Signing TBS data on provided private key + return crypto.sign(defParams.algorithm, + privateKey, + new Uint8Array(_this.tbsResponseData.tbs)).then( + function(result) + { + // #region Special case for ECDSA algorithm + if(defParams.algorithm.name === "ECDSA") + result = in_window.org.pkijs.createCMSECDSASignature(result); + // #endregion + + _this.signature = new in_window.org.pkijs.asn1.BITSTRING({ value_hex: result }); + }, + function(error) + { + return Promise.reject("Signing error: " + error); + } + ); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.OCSP_BASIC_RESPONSE.prototype.toJSON = + function() + { + var _object = { + tbsResponseData: this.tbsResponseData.toJSON(), + signatureAlgorithm: this.signatureAlgorithm.toJSON(), + signature: this.signature.toJSON() + }; + + if("certs" in this) + { + _object.certs = new Array(); + + for(var i = 0; i < this.certs.length; i++) + _object.certs.push(this.certs[i].toJSON()); + } + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.OCSP_BASIC_RESPONSE.prototype.getCertificateStatus = + function(certificate, issuerCertificate) + { + /// Get OCSP response status for specific certificate + /// Certificate to be checked + /// Certificate of issuer for certificate to be checked + + // #region Initial variables + var sequence = Promise.resolve(); + + var _this = this; + + var result = { + isForCertificate: false, + status: 2 // 0 = good, 1 = revoked, 2 = unknown + }; + + var hashesObject = {}; + + var certIDs = new Array(); + var certIDPromises = new Array(); + // #endregion + + // #region Create all "certIDs" for input certificates + for(var i = 0; i < this.tbsResponseData.responses.length; i++) + { + var hashAlgorithm = in_window.org.pkijs.getAlgorithmByOID(this.tbsResponseData.responses[i].certID.hashAlgorithm.algorithm_id); + if(("name" in hashAlgorithm) == false) + return Promise.reject("Wrong CertID hashing algorithm: " + this.tbsResponseData.responses[i].certID.hashAlgorithm.algorithm_id); + + if((hashAlgorithm.name in hashesObject) == false) + { + hashesObject[hashAlgorithm.name] = 1; + + var certID = new in_window.org.pkijs.simpl.ocsp.CertID(); + + certIDs.push(certID); + certIDPromises.push(certID.createForCertificate(certificate, { + hashAlgorithm: hashAlgorithm.name, + issuerCertificate: issuerCertificate + })); + } + } + + sequence = sequence.then( + function() + { + return Promise.all(certIDPromises); + } + ); + // #endregion + + // #region Compare all response's "certIDs" with identifiers for input certificate + sequence = sequence.then( + function() + { + for(var i = 0; i < _this.tbsResponseData.responses.length; i++) + { + for(var j = 0; j < certIDs.length; j++) + { + if(_this.tbsResponseData.responses[i].certID.isEqual(certIDs[j])) + { + result.isForCertificate = true; + + if(_this.tbsResponseData.responses[i].certStatus instanceof in_window.org.pkijs.asn1.ASN1_PRIMITIVE) + { + switch(_this.tbsResponseData.responses[i].certStatus.id_block.tag_number) + { + case 0: // good + result.status = 0; + break; + case 2: // unknown + result.status = 2; + break; + default:; + } + } + else + { + if(_this.tbsResponseData.responses[i].certStatus instanceof in_window.org.pkijs.asn1.ASN1_CONSTRUCTED) + { + if(_this.tbsResponseData.responses[i].certStatus.id_block.tag_number == 1) + result.status = 1; // revoked + } + } + + return result; + } + } + } + + return result; + } + ); + // #endregion + + return sequence; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "MessageImprint" type + //************************************************************************************** + in_window.org.pkijs.simpl.tsp.MessageImprint = + function() + { + // #region Internal properties of the object + this.hashAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.hashedMessage = new in_window.org.pkijs.asn1.OCTETSTRING(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.tsp.MessageImprint.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.hashAlgorithm = arguments[0].hashAlgorithm || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.hashedMessage = arguments[0].hashedMessage || new in_window.org.pkijs.asn1.OCTETSTRING(); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.tsp.MessageImprint.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.tsp.MessageImprint({ + names: { + hashAlgorithm: { + names: { + block_name: "hashAlgorithm" + } + }, + hashedMessage: "hashedMessage" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for MessageImprint"); + // #endregion + + // #region Get internal properties from parsed schema + this.hashAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["hashAlgorithm"] }); + this.hashedMessage = asn1.result["hashedMessage"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.tsp.MessageImprint.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + this.hashAlgorithm.toSchema(), + this.hashedMessage + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.tsp.MessageImprint.prototype.toJSON = + function() + { + return { + hashAlgorithm: this.hashAlgorithm.toJSON(), + hashedMessage: this.hashedMessage.toJSON() + }; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "TSP_REQUEST" type + //************************************************************************************** + in_window.org.pkijs.simpl.TSP_REQUEST = + function() + { + // #region Internal properties of the object + this.version = 0; + this.messageImprint = new in_window.org.pkijs.simpl.tsp.MessageImprint(); + // OPTIONAL this.reqPolicy = ""; + // OPTIONAL this.nonce = new in_window.org.pkijs.asn1.INTEGER(); + // OPTIONAL this.certReq = -1; // In order to designate that no schema value stored + // OPTIONAL this.extensions = new Array(); // Array of EXTENSION + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.TSP_REQUEST.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.version = arguments[0].version || 0; + this.messageImprint = arguments[0].messageImprint || new in_window.org.pkijs.simpl.tsp.MessageImprint(); + if("reqPolicy" in arguments[0]) + this.reqPolicy = arguments[0].reqPolicy; + if("nonce" in arguments[0]) + this.nonce = arguments[0].nonce; + if("certReq" in arguments[0]) + this.certReq = arguments[0].certReq; + if("extensions" in arguments[0]) + this.extensions = arguments[0].extensions; // Array of EXTENSION + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.TSP_REQUEST.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.TSP_REQUEST() + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for TSP_REQUEST"); + // #endregion + + // #region Get internal properties from parsed schema + this.version = asn1.result["TimeStampReq.version"].value_block.value_dec; + this.messageImprint = new in_window.org.pkijs.simpl.tsp.MessageImprint({ schema: asn1.result["TimeStampReq.messageImprint"] }); + if("TimeStampReq.reqPolicy" in asn1.result) + this.reqPolicy = asn1.result["TimeStampReq.reqPolicy"].value_block.toString(); + if("TimeStampReq.nonce" in asn1.result) + this.nonce = asn1.result["TimeStampReq.nonce"]; + if("TimeStampReq.certReq" in asn1.result) + this.certReq = asn1.result["TimeStampReq.certReq"].value_block.value; + if("TimeStampReq.extensions" in asn1.result) + { + this.extensions = new Array(); + + var extensions_array = asn1.result["TimeStampReq.extensions"]; + + for(var i = 0; i < extensions_array.length; i++) + this.extensions.push(new in_window.org.pkijs.simpl.EXTENSION({ schema: extensions_array[i] })); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.TSP_REQUEST.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + output_array.push(new in_window.org.pkijs.asn1.INTEGER({ value: this.version })); + output_array.push(this.messageImprint.toSchema()); + if("reqPolicy" in this) + output_array.push(new in_window.org.pkijs.asn1.OID({ value: this.reqPolicy })); + if("nonce" in this) + output_array.push(this.nonce); + if("certReq" in this) + output_array.push(new in_window.org.pkijs.asn1.BOOLEAN({ value: this.certReq })); + + // #region Create array of extensions + if("extensions" in this) + { + var extensions_array = new Array(); + + for(var i = 0; i < this.extensions.length; i++) + extensions_array.push(this.extensions[i].toSchema()); + + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: extensions_array + })); + } + // #endregion + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.TSP_REQUEST.prototype.toJSON = + function() + { + var _object = { + version: this.version, + messageImprint: this.messageImprint.toJSON() + }; + + if("reqPolicy" in this) + _object.reqPolicy = this.reqPolicy; + + if("nonce" in this) + _object.nonce = this.nonce.toJSON(); + + if("certReq" in this) + _object.certReq = this.certReq; + + if("extensions" in this) + { + _object.extensions = new Array(); + + for(var i = 0; i < this.extensions.length; i++) + _object.extensions.push(this.extensions[i].toJSON()); + } + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "Accuracy" type + //************************************************************************************** + in_window.org.pkijs.simpl.tsp.Accuracy = + function() + { + // #region Internal properties of the object + // OPTIONAL this.seconds = 0; + // OPTIONAL this.millis = 0; + // OPTIONAL this.micros = 0; + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.tsp.Accuracy.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + if("seconds" in arguments[0]) + this.seconds = arguments[0].seconds; + if("millis" in arguments[0]) + this.millis = arguments[0].millis; + if("micros" in arguments[0]) + this.micros = arguments[0].micros; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.tsp.Accuracy.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.tsp.Accuracy({ + names: { + seconds: "seconds", + millis: "millis", + micros: "micros" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for tsp.Accuracy"); + // #endregion + + // #region Get internal properties from parsed schema + if("seconds" in asn1.result) + this.seconds = asn1.result["seconds"].value_block.value_dec; + if("millis" in asn1.result) + { + var intMillis = new in_window.org.pkijs.asn1.INTEGER({ value_hex: asn1.result["millis"].value_block.value_hex }); + this.millis = intMillis.value_block.value_dec; + } + if("micros" in asn1.result) + { + var intMicros = new in_window.org.pkijs.asn1.INTEGER({ value_hex: asn1.result["micros"].value_block.value_hex }); + this.micros = intMicros.value_block.value_dec; + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.tsp.Accuracy.prototype.toSchema = + function() + { + // #region Create array of output sequence + var output_array = new Array(); + + if("seconds" in this) + output_array.push(new in_window.org.pkijs.asn1.INTEGER({ value: this.seconds })); + if("millis" in this) + { + var intMillis = new in_window.org.pkijs.asn1.INTEGER({ value: this.millis }); + + output_array.push(new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value_hex: intMillis.value_block.value_hex + })); + } + if("micros" in this) + { + var intMicros = new in_window.org.pkijs.asn1.INTEGER({ value: this.micros }); + + output_array.push(new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value_hex: intMicros.value_block.value_hex + })); + } + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.tsp.Accuracy.prototype.toJSON = + function() + { + var _object = {}; + + if("seconds" in this) + _object.seconds = this.seconds; + + if("millis" in this) + _object.millis = this.millis; + + if("micros" in this) + _object.micros = this.micros; + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "TST_INFO" type + //************************************************************************************** + in_window.org.pkijs.simpl.TST_INFO = + function() + { + // #region Internal properties of the object + this.version = 0; + this.policy = ""; + this.messageImprint = new in_window.org.pkijs.simpl.tsp.MessageImprint(); + this.serialNumber = new in_window.org.pkijs.asn1.INTEGER(); + this.genTime = new Date(0, 0, 0); + // OPTIONAL this.accuracy = new in_window.org.pkijs.simpl.tsp.Accuracy(); + // OPTIONAL this.ordering = -1; // In order to designate uninitialized value + // OPTIONAL this.nonce = new in_window.org.pkijs.asn1.INTEGER(); + // OPTIONAL this.tsa = new in_window.org.pkijs.simpl.GENERAL_NAME(); + // OPTIONAL this.extensions = new Array(); // Array of EXTENSION + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.TST_INFO.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.version = arguments[0].version || 0; + this.policy = arguments[0].policy || ""; + this.messageImprint = arguments[0].messageImprint || new in_window.org.pkijs.simpl.tsp.MessageImprint(); + this.serialNumber = arguments[0].serialNumber || new in_window.org.pkijs.asn1.INTEGER(); + this.genTime = arguments[0].genTime || new Date(0, 0, 0); + if("accuracy" in arguments[0]) + this.accuracy = arguments[0].accuracy; + if("ordering" in arguments[0]) + this.ordering = arguments[0].ordering; + if("nonce" in arguments[0]) + this.nonce = arguments[0].nonce; + if("tsa" in arguments[0]) + this.tsa = arguments[0].tsa; + if("extensions" in arguments[0]) + this.extensions = arguments[0].extensions; // Array of EXTENSION + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.TST_INFO.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.TST_INFO() + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for TST_INFO"); + // #endregion + + // #region Get internal properties from parsed schema + this.version = asn1.result["TSTInfo.version"].value_block.value_dec; + this.policy = asn1.result["TSTInfo.policy"].value_block.toString(); + this.messageImprint = new in_window.org.pkijs.simpl.tsp.MessageImprint({ schema: asn1.result["TSTInfo.messageImprint"] }); + this.serialNumber = asn1.result["TSTInfo.serialNumber"]; + this.genTime = asn1.result["TSTInfo.genTime"].toDate(); + if("TSTInfo.accuracy" in asn1.result) + this.accuracy = new in_window.org.pkijs.simpl.tsp.Accuracy({ schema: asn1.result["TSTInfo.accuracy"] }); + if("TSTInfo.ordering" in asn1.result) + this.ordering = asn1.result["TSTInfo.ordering"].value_block.value; + if("TSTInfo.nonce" in asn1.result) + this.nonce = asn1.result["TSTInfo.nonce"]; + if("TSTInfo.tsa" in asn1.result) + this.tsa = new in_window.org.pkijs.simpl.GENERAL_NAME({ schema: asn1.result["TSTInfo.tsa"] }); + if("TSTInfo.extensions" in asn1.result) + { + var extensions_array = asn1.result["TSTInfo.extensions"]; + + for(var i = 0; i < extensions_array.length; i++) + this.extensions.push(new in_window.org.pkijs.simpl.EXTENSION({ schema: extensions_array[i] })); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.TST_INFO.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + output_array.push(new in_window.org.pkijs.asn1.INTEGER({ value: this.version })); + output_array.push(new in_window.org.pkijs.asn1.OID({ value: this.policy })); + output_array.push(this.messageImprint.toSchema()); + output_array.push(this.serialNumber); + output_array.push(new in_window.org.pkijs.asn1.GENERALIZEDTIME({ value_date: this.genTime })); + if("accuracy" in this) + output_array.push(this.accuracy.toSchema()); + if("ordering" in this) + output_array.push(new in_window.org.pkijs.asn1.BOOLEAN({ value: this.ordering })); + if("nonce" in this) + output_array.push(this.nonce); + if("tsa" in this) + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [this.tsa.toSchema()] + })); + + // #region Create array of extensions + if("extensions" in this) + { + var extensions_array = new Array(); + + for(var i = 0; i < this.extensions.length; i++) + extensions_array.push(this.extensions[i].toSchema()); + + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: extensions_array + })); + } + // #endregion + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.TST_INFO.prototype.toJSON = + function() + { + var _object = { + version: this.version, + policy: this.policy, + messageImprint: this.messageImprint.toJSON(), + serialNumber: this.serialNumber.toJSON(), + genTime: this.genTime + }; + + if("accuracy" in this) + _object.accuracy = this.accuracy.toJSON(); + + if("ordering" in this) + _object.ordering = this.ordering; + + if("nonce" in this) + _object.nonce = this.nonce.toJSON(); + + if("tsa" in this) + _object.tsa = this.tsa.toJSON(); + + if("extensions" in this) + { + _object.extensions = new Array(); + + for(var i = 0; i < this.extensions.length; i++) + _object.extensions.push(this.extensions[i].toJSON()); + } + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.TST_INFO.prototype.verify = + function() + { + // #region Initial variables + var sequence = Promise.resolve(); + + var _this = this; + + var data; + + var notBefore; + var notAfter; + // #endregion + + // #region Get a "crypto" extension + var crypto = in_window.org.pkijs.getCrypto(); + if(typeof crypto == "undefined") + return Promise.reject("Unable to create WebCrypto object"); + // #endregion + + // #region Get initial parameters + if(arguments[0] instanceof Object) + { + if("data" in arguments[0]) + data = arguments[0].data; + else + return Promise.reject("\"data\" is a mandatory attribute for TST_INFO verification"); + + if("notBefore" in arguments[0]) + notBefore = arguments[0].notBefore; + + if("notAfter" in arguments[0]) + notAfter = arguments[0].notAfter; + } + // #endregion + + // #region Find hashing algorithm + var shaAlgorithm = in_window.org.pkijs.getAlgorithmByOID(_this.messageImprint.hashAlgorithm.algorithm_id); + if(("name" in shaAlgorithm) === false) + return Promise.reject("Unsupported signature algorithm: " + _this.messageImprint.hashAlgorithm.algorithm_id); + + var sha_algorithm = shaAlgorithm.name; + // #endregion + + // #region Calculate message digest for input "data" buffer + sequence = sequence.then( + function() + { + return crypto.digest(sha_algorithm, new Uint8Array(data)); + } + ).then( + function(result) + { + return !!in_window.org.pkijs.isEqual_buffer(result, _this.messageImprint.hashedMessage.value_block.value_hex); + } + ); + // #endregion + + return sequence; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "PKIStatusInfo" type + //************************************************************************************** + in_window.org.pkijs.simpl.tsp.PKIStatusInfo = + function() + { + // #region Internal properties of the object + this.status = 2; // rejection + // OPTIONAL this.statusStrings = new Array(); // Array of UTF8STRING + // OPTIONAL this.failInfo = new in_window.org.pkijs.asn1.BITSTRING(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.tsp.PKIStatusInfo.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.status = in_window.org.pkijs.getValue(arguments[0], "status", 2); + if("statusStrings" in arguments[0]) + this.statusStrings = arguments[0].statusStrings; // Array of UTF8STRING + if("failInfo" in arguments[0]) + this.failInfo = arguments[0].failInfo; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.tsp.PKIStatusInfo.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.tsp.PKIStatusInfo({ + names: { + status: "status", + statusStrings: "statusStrings", + failInfo: "failInfo" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for PKIStatusInfo"); + // #endregion + + // #region Get internal properties from parsed schema + var _status = asn1.result["status"]; + + if((_status.value_block.is_hex_only === true) || + (_status.value_block.value_dec < 0) || + (_status.value_block.value_dec > 5)) + { + throw new Error("PKIStatusInfo \"status\" has invalid value"); + } + + this.status = _status.value_block.value_dec; + + if("statusStrings" in asn1.result) + this.statusStrings = asn1.result["statusStrings"]; + if("failInfo" in asn1.result) + this.failInfo = asn1.result["failInfo"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.tsp.PKIStatusInfo.prototype.toSchema = + function() + { + // #region Create array of output sequence + var output_array = new Array(); + + output_array.push(new in_window.org.pkijs.asn1.INTEGER({ value: this.status })); + if("statusStrings" in this) + output_array.push(new in_window.org.pkijs.asn1.SEQUENCE({ + value: this.statusStrings + })); + if("failInfo" in this) + output_array.push(this.failInfo); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.tsp.PKIStatusInfo.prototype.toJSON = + function() + { + var _object = { + status: this.status + }; + + if("statusStrings" in this) + { + _object.statusStrings = new Array(); + + for(var i = 0; i < this.statusStrings.length; i++) + _object.statusStrings.push(this.statusStrings[i].toJSON()); + } + + if("failInfo" in this) + _object.failInfo = this.failInfo.toJSON(); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "TSP_RESPONSE" type + //************************************************************************************** + in_window.org.pkijs.simpl.TSP_RESPONSE = + function() + { + // #region Internal properties of the object + this.status = new in_window.org.pkijs.simpl.tsp.PKIStatusInfo(); + // OPTIONAL this.timeStampToken = new in_window.org.pkijs.simpl.CMS_CONTENT_INFO(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.TSP_RESPONSE.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.status = arguments[0].status || new in_window.org.pkijs.simpl.tsp.PKIStatusInfo(); + if("timeStampToken" in arguments[0]) + this.timeStampToken = arguments[0].timeStampToken; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.TSP_RESPONSE.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.TSP_RESPONSE() + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for TSP_RESPONSE"); + // #endregion + + // #region Get internal properties from parsed schema + this.status = new in_window.org.pkijs.simpl.tsp.PKIStatusInfo({ schema: asn1.result["TimeStampResp.status"] }); + if("TimeStampResp.timeStampToken" in asn1.result) + this.timeStampToken = new in_window.org.pkijs.simpl.CMS_CONTENT_INFO({ schema: asn1.result["TimeStampResp.timeStampToken"] }); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.TSP_RESPONSE.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + output_array.push(this.status.toSchema()); + if("timeStampToken" in this) + output_array.push(this.timeStampToken.toSchema()); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.TSP_RESPONSE.prototype.verify = + function() + { + /// !!! Works well in Chrome dev versions only (April 2014th) !!! + /// Returns a new Promise object (in case of error), or a result of "crypto.subtle.veryfy" function + + // #region Initial variables + var verificationParameters = { + signer: 0, + trusted_certs: [], + data: new ArrayBuffer(0) + }; + // #endregion + + // #region Check that "timeStampToken" exists + if(("timeStampToken" in this) === false) + return Promise.reject("timeStampToken is absent in TSP response"); + // #endregion + + // #region Get initial parameters + if(arguments[0] instanceof Object) + { + verificationParameters = arguments[0]; + verificationParameters.signer = 0; + } + // #endregion + + // #region Check that "timeStampToken" has a right internal format + if(this.timeStampToken.contentType !== "1.2.840.113549.1.7.2") // Must be a CMS signed data + return Promise.reject("Wrong format of timeStampToken: " + _this.timeStampToken.contentType); + // #endregion + + // #region Verify internal signed data value + var signed_simp = new in_window.org.pkijs.simpl.CMS_SIGNED_DATA({ schema: this.timeStampToken.content }); + + return signed_simp.verify(verificationParameters); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.TSP_RESPONSE.prototype.sign = + function(privateKey, hashAlgorithm) + { + /// Private key for "subjectPublicKeyInfo" structure + /// Hashing algorithm. Default SHA-1 + + var _this = this; + + // #region Check that "timeStampToken" exists + if(("timeStampToken" in this) === false) + return Promise.reject("timeStampToken is absent in TSP response"); + // #endregion + + // #region Check that "timeStampToken" has a right internal format + if(this.timeStampToken.contentType !== "1.2.840.113549.1.7.2") // Must be a CMS signed data + return Promise.reject("Wrong format of timeStampToken: " + _this.timeStampToken.contentType); + // #endregion + + // #region Sign internal signed data value + var signed_simp = new in_window.org.pkijs.simpl.CMS_SIGNED_DATA({ schema: this.timeStampToken.content }); + + return signed_simp.sign(privateKey, 0, hashAlgorithm); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.TSP_RESPONSE.prototype.toJSON = + function() + { + var _object = { + status: this.status + }; + + if("timeStampToken" in this) + _object.timeStampToken = this.timeStampToken.toJSON(); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** +} +)(typeof exports !== "undefined" ? exports : window); \ No newline at end of file diff --git a/express-server/node_modules/pkijs/org/pkijs/pkcs12_schema.js b/express-server/node_modules/pkijs/org/pkijs/pkcs12_schema.js new file mode 100644 index 00000000..858fe2b9 --- /dev/null +++ b/express-server/node_modules/pkijs/org/pkijs/pkcs12_schema.js @@ -0,0 +1,413 @@ +/* + * Copyright (c) 2015, Peculiar Ventures + * All rights reserved. + * + * Author 2015, Yury Strozhevsky . + * + * 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 copyright holder 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. + * + */ +( +function(in_window) +{ + //************************************************************************************** + // #region Declaration of global variables + //************************************************************************************** + // #region "org" namespace + if(typeof in_window.org === "undefined") + in_window.org = {}; + else + { + if(typeof in_window.org !== "object") + throw new Error("Name org already exists and it's not an object"); + } + // #endregion + + // #region "org.pkijs" namespace + if(typeof in_window.org.pkijs === "undefined") + in_window.org.pkijs = {}; + else + { + if(typeof in_window.org.pkijs !== "object") + throw new Error("Name org.pkijs already exists and it's not an object" + " but " + (typeof in_window.org.pkijs)); + } + // #endregion + + // #region "org.pkijs.schema" namespace + if(typeof in_window.org.pkijs.schema === "undefined") + in_window.org.pkijs.schema = {}; + else + { + if(typeof in_window.org.pkijs.schema !== "object") + throw new Error("Name org.pkijs.schema already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.schema)); + } + // #endregion + + // #region "org.pkijs.schema.cms" namespace + if(typeof in_window.org.pkijs.schema.pkcs12 === "undefined") + in_window.org.pkijs.schema.pkcs12 = {}; + else + { + if(typeof in_window.org.pkijs.schema.pkcs12 !== "object") + throw new Error("Name org.pkijs.schema.pkcs12 already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.schema.pkcs12)); + } + // #endregion + + // #region "local" namespace + var local = {}; + // #endregion + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "DigestInfo" type (RFC2315) + //************************************************************************************** + in_window.org.pkijs.schema.DigestInfo = + function() + { + //DigestInfo ::= SEQUENCE { + // digestAlgorithm DigestAlgorithmIdentifier, + // digest Digest } + + //Digest ::= OCTET STRING + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.digestAlgorithm || { + names: { + block_name: "digestAlgorithm" + } + }), + new in_window.org.pkijs.asn1.OCTETSTRING({ name: (names.digest || "digest") }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "MacData" type (RFC7292) + //************************************************************************************** + in_window.org.pkijs.schema.pkcs12.MacData = + function() + { + //MacData ::= SEQUENCE { + // mac DigestInfo, + // macSalt OCTET STRING, + // iterations INTEGER DEFAULT 1 + // -- Note: The default is for historical reasons and its use is + // -- deprecated. A higher value, like 1024 is recommended. + // } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + optional: (names.optional || true), + value: [ + in_window.org.pkijs.schema.DigestInfo(names.mac || { + names: { + block_name: "mac" + } + }), + new in_window.org.pkijs.asn1.OCTETSTRING({ name: (names.macSalt || "macSalt") }), + new in_window.org.pkijs.asn1.INTEGER({ + optional: true, + name: (names.iterations || "iterations") + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "PFX" type (RFC7292) + //************************************************************************************** + in_window.org.pkijs.schema.PFX = + function() + { + //PFX ::= SEQUENCE { + // version INTEGER {v3(3)}(v3,...), + // authSafe ContentInfo, + // macData MacData OPTIONAL + //} + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.INTEGER({ name: (names.version || "version") }), + in_window.org.pkijs.schema.CMS_CONTENT_INFO(names.authSafe || { + names: { + block_name: "authSafe" + } + }), + in_window.org.pkijs.schema.pkcs12.MacData(names.macData || { + names: { + block_name: "macData", + optional: true + } + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "AuthenticatedSafe" type (RFC7292) + //************************************************************************************** + in_window.org.pkijs.schema.pkcs12.AuthenticatedSafe = + function() + { + //AuthenticatedSafe ::= SEQUENCE OF ContentInfo + //-- Data if unencrypted + //-- EncryptedData if password-encrypted + //-- EnvelopedData if public key-encrypted + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.contentInfos || ""), + value: in_window.org.pkijs.schema.CMS_CONTENT_INFO() + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "SafeBag" type (RFC7292) + //************************************************************************************** + in_window.org.pkijs.schema.pkcs12.SafeBag = + function() + { + //SafeBag ::= SEQUENCE { + // bagId BAG-TYPE.&id ({PKCS12BagSet}), + // bagValue [0] EXPLICIT BAG-TYPE.&Type({PKCS12BagSet}{@bagId}), + // bagAttributes SET OF PKCS12Attribute OPTIONAL + //} + + //rsadsi OBJECT IDENTIFIER ::= {iso(1) member-body(2) us(840) rsadsi(113549)} + //pkcs OBJECT IDENTIFIER ::= {rsadsi pkcs(1)} + //pkcs-12 OBJECT IDENTIFIER ::= {pkcs 12} + + //bagtypes OBJECT IDENTIFIER ::= {pkcs-12 10 1} + + //keyBag BAG-TYPE ::= + //{KeyBag IDENTIFIED BY {bagtypes 1}} + //pkcs8ShroudedKeyBag BAG-TYPE ::= + //{PKCS8ShroudedKeyBag IDENTIFIED BY {bagtypes 2}} + //certBag BAG-TYPE ::= + //{CertBag IDENTIFIED BY {bagtypes 3}} + //crlBag BAG-TYPE ::= + //{CRLBag IDENTIFIED BY {bagtypes 4}} + //secretBag BAG-TYPE ::= + //{SecretBag IDENTIFIED BY {bagtypes 5}} + //safeContentsBag BAG-TYPE ::= + //{SafeContents IDENTIFIED BY {bagtypes 6}} + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.OID({ name: (names.bagId || "bagId") }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [new in_window.org.pkijs.asn1.ANY({ name: (names.bagValue || "bagValue") })] // EXPLICIT ANY value + }), + new in_window.org.pkijs.asn1.SET({ + optional: true, + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.bagAttributes || "bagAttributes"), + value: in_window.org.pkijs.schema.cms.Attribute() + }) + ] + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "SafeContents" type (RFC7292) + //************************************************************************************** + in_window.org.pkijs.schema.pkcs12.SafeContents = + function() + { + //SafeContents ::= SEQUENCE OF SafeBag + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.safeBags || ""), + value: in_window.org.pkijs.schema.pkcs12.SafeBag() + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "KeyBag" type (RFC7292) + //************************************************************************************** + in_window.org.pkijs.schema.pkcs12.KeyBag = + function() + { + return in_window.org.pkijs.schema.PKCS8.apply(null, arguments); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "PKCS8ShroudedKeyBag" type (RFC7292) + //************************************************************************************** + in_window.org.pkijs.schema.pkcs12.PKCS8ShroudedKeyBag = + function() + { + //PKCS8ShroudedKeyBag ::= EncryptedPrivateKeyInfo + + //EncryptedPrivateKeyInfo ::= SEQUENCE { + // encryptionAlgorithm AlgorithmIdentifier {{KeyEncryptionAlgorithms}}, + // encryptedData EncryptedData + //} + + //EncryptedData ::= OCTET STRING + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.hashAlgorithm || { + names: { + block_name: "encryptionAlgorithm" + } + }), + new in_window.org.pkijs.asn1.CHOICE({ + value: [ + new in_window.org.pkijs.asn1.OCTETSTRING({ name: (names.encryptedData || "encryptedData") }), + new in_window.org.pkijs.asn1.OCTETSTRING({ + id_block: { + is_constructed: true + }, + name: (names.encryptedData || "encryptedData") + }) + ] + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "local.StandardBag" type + //************************************************************************************** + local.StandardBag = + function() + { + //SEQUENCE { + // certId BAG-TYPE.&id ({CertTypes}), + // certValue [0] EXPLICIT BAG-TYPE.&Type ({CertTypes}{@certId}) + //} + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.OID({ name: (names.id || "id") }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [new in_window.org.pkijs.asn1.ANY({ name: (names.value || "value") })] // EXPLICIT ANY value + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "CertBag" type (RFC7292) + //************************************************************************************** + in_window.org.pkijs.schema.pkcs12.CertBag = + function() + { + //CertBag ::= SEQUENCE { + // certId BAG-TYPE.&id ({CertTypes}), + // certValue [0] EXPLICIT BAG-TYPE.&Type ({CertTypes}{@certId}) + //} + + return local.StandardBag.apply(null, arguments); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "CRLBag" type (RFC7292) + //************************************************************************************** + in_window.org.pkijs.schema.pkcs12.CRLBag = + function() + { + //CRLBag ::= SEQUENCE { + // crlId BAG-TYPE.&id ({CRLTypes}), + // crlValue [0] EXPLICIT BAG-TYPE.&Type ({CRLTypes}{@crlId}) + //} + + return local.StandardBag.apply(null, arguments); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "SecretBag" type (RFC7292) + //************************************************************************************** + in_window.org.pkijs.schema.pkcs12.SecretBag = + function() + { + //SecretBag ::= SEQUENCE { + // secretTypeId BAG-TYPE.&id ({SecretTypes}), + // secretValue [0] EXPLICIT BAG-TYPE.&Type ({SecretTypes}{@secretTypeId}) + //} + + return local.StandardBag.apply(null, arguments); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** +} +)(typeof exports !== "undefined" ? exports : window); \ No newline at end of file diff --git a/express-server/node_modules/pkijs/org/pkijs/pkcs12_simpl.js b/express-server/node_modules/pkijs/org/pkijs/pkcs12_simpl.js new file mode 100644 index 00000000..58ea50ec --- /dev/null +++ b/express-server/node_modules/pkijs/org/pkijs/pkcs12_simpl.js @@ -0,0 +1,2069 @@ +/* + * Copyright (c) 2015, Peculiar Ventures + * All rights reserved. + * + * Author 2015, Yury Strozhevsky . + * + * 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 copyright holder 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. + * + */ +( +function(in_window) +{ + //************************************************************************************** + // #region Declaration of global variables + //************************************************************************************** + // #region "org" namespace + if(typeof in_window.org === "undefined") + in_window.org = {}; + else + { + if(typeof in_window.org !== "object") + throw new Error("Name org already exists and it's not an object"); + } + // #endregion + + // #region "org.pkijs" namespace + if(typeof in_window.org.pkijs === "undefined") + in_window.org.pkijs = {}; + else + { + if(typeof in_window.org.pkijs !== "object") + throw new Error("Name org.pkijs already exists and it's not an object" + " but " + (typeof in_window.org.pkijs)); + } + // #endregion + + // #region "org.pkijs.simpl" namespace + if(typeof in_window.org.pkijs.simpl === "undefined") + in_window.org.pkijs.simpl = {}; + else + { + if(typeof in_window.org.pkijs.simpl !== "object") + throw new Error("Name org.pkijs.simpl already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.simpl)); + } + // #endregion + + // #region "org.pkijs.simpl.pkcs12" namespace + if(typeof in_window.org.pkijs.simpl.pkcs12 === "undefined") + in_window.org.pkijs.simpl.pkcs12 = {}; + else + { + if(typeof in_window.org.pkijs.simpl.pkcs12 !== "object") + throw new Error("Name org.pkijs.simpl.pkcs12 already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.simpl.pkcs12)); + } + // #endregion + + // #region "local" namespace + var local = {}; + // #endregion + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "DigestInfo" type + //************************************************************************************** + in_window.org.pkijs.simpl.DigestInfo = + function() + { + // #region Internal properties of the object + this.digestAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.digest = new in_window.org.pkijs.asn1.OCTETSTRING(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.DigestInfo.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.digestAlgorithm = (arguments[0].digestAlgorithm || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER()); + this.digest = (arguments[0].digest || new in_window.org.pkijs.asn1.OCTETSTRING()); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.DigestInfo.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.DigestInfo({ + names: { + digestAlgorithm: { + names: { + block_name: "digestAlgorithm" + } + }, + digest: "digest" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for DigestInfo"); + // #endregion + + // #region Get internal properties from parsed schema + this.digestAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["digestAlgorithm"] }); + this.digest = asn1.result["digest"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.DigestInfo.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + this.digestAlgorithm.toSchema(), + this.digest + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.DigestInfo.prototype.toJSON = + function() + { + return { + digestAlgorithm: this.digestAlgorithm.toJSON(), + digest: this.digest.toJSON() + }; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "MacData" type + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.MacData = + function() + { + // #region Internal properties of the object + this.mac = new in_window.org.pkijs.simpl.DigestInfo(); + this.macSalt = new in_window.org.pkijs.asn1.OCTETSTRING(); + // OPTIONAL this.iterations = 1; + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.pkcs12.MacData.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.mac = (arguments[0].mac || new in_window.org.pkijs.simpl.DigestInfo()); + this.macSalt = (arguments[0].macSalt || new in_window.org.pkijs.asn1.OCTETSTRING()); + + if("iterations" in arguments[0]) + this.iterations = arguments[0].iterations; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.MacData.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.pkcs12.MacData({ + names: { + mac: { + names: { + block_name: "mac" + } + }, + macSalt: "macSalt", + iterations: "iterations" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for MacData"); + // #endregion + + // #region Get internal properties from parsed schema + this.mac = new in_window.org.pkijs.simpl.DigestInfo({ schema: asn1.result["mac"] }); + this.macSalt = asn1.result["macSalt"]; + + if("iterations" in asn1.result) + this.iterations = asn1.result["iterations"].value_block.value_dec; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.MacData.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + var output_array = [ + this.mac.toSchema(), + this.macSalt + ]; + + if("iterations" in this) + output_array.push(new in_window.org.pkijs.asn1.INTEGER({ value: this.iterations })); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.MacData.prototype.toJSON = + function() + { + var output = { + mac: this.mac.toJSON(), + macSalt: this.macSalt.toJSON() + }; + + if("iterations" in this) + output.iterations = this.iterations.toJSON(); + + return output; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "PFX" type + //************************************************************************************** + in_window.org.pkijs.simpl.PFX = + function() + { + // #region Internal properties of the object + this.version = 3; + this.authSafe = new in_window.org.pkijs.simpl.CMS_CONTENT_INFO(); + // OPTIONAL this.macData = new in_window.org.pkijs.simpl.pkcs12.MacData(); + + // OPTIONAL this.parsedValue = {}; // Object having all parsed data from initial "authSafe" + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.PFX.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.version = (arguments[0].version || 3); + this.authSafe = (arguments[0].authSafe || new in_window.org.pkijs.simpl.CMS_CONTENT_INFO()); + + if("macData" in arguments[0]) + this.macData = arguments[0].macData; + + if("parsedValue" in arguments[0]) + this.parsedValue = arguments[0].parsedValue; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.PFX.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.PFX({ + names: { + version: "version", + authSafe: { + names: { + block_name: "authSafe" + } + }, + macData: { + names: { + block_name: "macData" + } + } + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for PFX"); + // #endregion + + // #region Get internal properties from parsed schema + this.version = asn1.result["version"].value_block.value_dec; + this.authSafe = new in_window.org.pkijs.simpl.CMS_CONTENT_INFO({ schema: asn1.result["authSafe"] }); + + if("macData" in asn1.result) + this.macData = new in_window.org.pkijs.simpl.pkcs12.MacData({ schema: asn1.result["macData"] }); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.PFX.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + var output_array = [ + new in_window.org.pkijs.asn1.INTEGER({ value: this.version }), + this.authSafe.toSchema() + ]; + + if("macData" in this) + output_array.push(this.macData.toSchema()); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.PFX.prototype.toJSON = + function() + { + var output = { + version: this.version, + authSafe: this.authSafe.toJSON() + }; + + if("macData" in this) + output.macData = this.macData.toJSON(); + + return output; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.PFX.prototype.makeInternalValues = + function(parameters) + { + /// Making "CMS_CONTENT_INFO" from "parsedValue" object + /// Parameters, specific to each "integrity mode" + + // #region Check mandatory parameter + if((parameters instanceof Object) == false) + return Promise.reject("The \"parameters\" must has \"Object\" type"); + + if(("parsedValue" in this) == false) + return Promise.reject("Please call \"parseValues\" function first in order to make \"parsedValue\" data"); + + if(("integrityMode" in this.parsedValue) == false) + return Promise.reject("Absent mandatory parameter \"integrityMode\" inside \"parsedValue\""); + // #endregion + + // #region Initial variables + var _this = this; + var sequence = Promise.resolve(); + // #endregion + + // #region Get a "crypto" extension + var crypto = in_window.org.pkijs.getCrypto(); + if(typeof crypto == "undefined") + return Promise.reject("Unable to create WebCrypto object"); + // #endregion + + // #region Makes values for each particular integrity mode + // #region Check that we do have neccessary fields in "parsedValue" object + if(("authenticatedSafe" in _this.parsedValue) == false) + return Promise.reject("Absent mandatory parameter \"authenticatedSafe\" in \"parsedValue\""); + // #endregion + + switch(this.parsedValue.integrityMode) + { + // #region HMAC-based integrity + case 0: + { + // #region Check additional mandatory parameters + if(("iterations" in parameters) == false) + return Promise.reject("Absent mandatory parameter \"iterations\""); + + if(("pbkdf2HashAlgorithm" in parameters) == false) + return Promise.reject("Absent mandatory parameter \"pbkdf2HashAlgorithm\""); + + if(("hmacHashAlgorithm" in parameters) == false) + return Promise.reject("Absent mandatory parameter \"hmacHashAlgorithm\""); + + if(("password" in parameters) == false) + return Promise.reject("Absent mandatory parameter \"password\""); + // #endregion + + // #region Initial variables + var saltBuffer = new ArrayBuffer(64); + var saltView = new Uint8Array(saltBuffer); + + in_window.org.pkijs.getRandomValues(saltView); + + var length; + + // #region Choose correct length for HMAC key + switch(parameters.hmacHashAlgorithm.toLowerCase()) + { + case "sha-1": + length = 160; + break; + case "sha-256": + length = 256; + break; + case "sha-384": + length = 384; + break; + case "sha-512": + length = 512; + break; + default: + return Promise.reject("Incorrect \"parameters.hmacHashAlgorithm\" parameter: " + parameters.hmacHashAlgorithm); + } + // #endregion + + var hmacAlgorithm = { + name: "HMAC", + length: length, + hash: { + name: parameters.hmacHashAlgorithm + } + }; + // #endregion + + // #region Generate HMAC key using PBKDF2 + // #region Derive PBKDF2 key from "password" buffer + sequence = sequence.then( + function(result) + { + var passwordView = new Uint8Array(parameters.password); + + return crypto.importKey("raw", + passwordView, + "PBKDF2", + true, + ['deriveKey']); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + // #region Derive key for HMAC + sequence = sequence.then( + function(result) + { + return crypto.deriveKey({ + name: "PBKDF2", + hash: { + name: parameters.pbkdf2HashAlgorithm + }, + salt: saltView, + iterations: parameters.iterations + }, + result, + hmacAlgorithm, + true, + ['sign']); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #endregion + + // #region Make final "MacData" value + // #region Make signed HMAC value + sequence = sequence.then( + function(result) + { + _this.authSafe = new in_window.org.pkijs.simpl.CMS_CONTENT_INFO({ + contentType: "1.2.840.113549.1.7.1", + content: new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: _this.parsedValue.authenticatedSafe.toSchema().toBER(false) }) + }); + + var data = _this.authSafe.content.toBER(false); + var view = new Uint8Array(data); + + return crypto.sign(hmacAlgorithm, result, view); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + // #region Make "MacData" values + sequence = sequence.then( + function(result) + { + _this.macData = new in_window.org.pkijs.simpl.pkcs12.MacData({ + mac: new in_window.org.pkijs.simpl.DigestInfo({ + digestAlgorithm: new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: in_window.org.pkijs.getOIDByAlgorithm({ name: parameters.hmacHashAlgorithm }) + }), + digest: new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: result }) + }), + macSalt: new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: saltBuffer }), + iterations: parameters.iterations + }); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #endregion + } + break; + // #endregion + // #region publicKey-based integrity + case 1: + { + // #region Check additional mandatory parameters + if(("signingCertificate" in parameters) == false) + return Promise.reject("Absent mandatory parameter \"signingCertificate\""); + + if(("privateKey" in parameters) == false) + return Promise.reject("Absent mandatory parameter \"privateKey\""); + + if(("hashAlgorithm" in parameters) == false) + return Promise.reject("Absent mandatory parameter \"hashAlgorithm\""); + // #endregion + + // #region Making data to be signed + // NOTE: all internal data for "authenticatedSafe" must be already prepared. + // Thus user must call "makeValues" for all internal "SafeContent" value with appropriate parameters. + // Or user can choose to use values from initial parsing of existing PKCS#12 data. + + var toBeSigned = _this.parsedValue.authenticatedSafe.toSchema().toBER(false); + // #endregion + + // #region Initial variables + var cms_signed_simpl = new in_window.org.pkijs.simpl.CMS_SIGNED_DATA({ + version: 1, + encapContentInfo: new in_window.org.pkijs.simpl.cms.EncapsulatedContentInfo({ + eContentType: "1.2.840.113549.1.7.1", // "data" content type + eContent: new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: toBeSigned }) + }), + certificates: [parameters.signingCertificate] + }); + // #endregion + + // #region Making additional attributes for CMS Signed Data + // #region Create a message digest + sequence = sequence.then( + function() + { + return crypto.digest({ name: parameters.hashAlgorithm }, new Uint8Array(toBeSigned)); + } + ); + // #endregion + + // #region Combine all signed extensions + sequence = sequence.then( + function(result) + { + // #region Initial variables + var signed_attr = new Array(); + // #endregion + + // #region contentType + signed_attr.push(new in_window.org.pkijs.simpl.cms.Attribute({ + attrType: "1.2.840.113549.1.9.3", + attrValues: [ + new in_window.org.pkijs.asn1.OID({ value: "1.2.840.113549.1.7.1" }) + ] + })); + // #endregion + // #region signingTime + signed_attr.push(new in_window.org.pkijs.simpl.cms.Attribute({ + attrType: "1.2.840.113549.1.9.5", + attrValues: [ + new in_window.org.pkijs.asn1.UTCTIME({ value_date: new Date() }) + ] + })); + // #endregion + // #region messageDigest + signed_attr.push(new in_window.org.pkijs.simpl.cms.Attribute({ + attrType: "1.2.840.113549.1.9.4", + attrValues: [ + new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: result }) + ] + })); + // #endregion + + // #region Making final value for "SignerInfo" type + cms_signed_simpl.signerInfos.push(new in_window.org.pkijs.simpl.CMS_SIGNER_INFO({ + version: 1, + sid: new in_window.org.pkijs.simpl.cms.IssuerAndSerialNumber({ + issuer: parameters.signingCertificate.issuer, + serialNumber: parameters.signingCertificate.serialNumber + }), + signedAttrs: new in_window.org.pkijs.simpl.cms.SignedUnsignedAttributes({ + type: 0, + attributes: signed_attr + }) + })); + // #endregion + }, + function(error) + { + return Promise.reject("Error during making digest for message: " + error); + } + ); + // #endregion + // #endregion + + // #region Signing CMS Signed Data + sequence = sequence.then( + function() + { + return cms_signed_simpl.sign(parameters.privateKey, 0, parameters.hashAlgorithm); + } + ); + // #endregion + + // #region Making final CMS_CONTENT_INFO type + sequence = sequence.then( + function(result) + { + _this.authSafe = new in_window.org.pkijs.simpl.CMS_CONTENT_INFO({ + contentType: "1.2.840.113549.1.7.2", + content: cms_signed_simpl.toSchema(true) + }); + }, + function(error) + { + return Promise.reject("Error during making signature: " + error); + } + ); + // #endregion + } + break; + // #endregion + // #region default + default: + return Promise.reject("Parameter \"integrityMode\" has unknown value: " + parameters.integrityMode); + // #endregion + } + // #endregion + + return sequence; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.PFX.prototype.parseInternalValues = + function(parameters) + { + // #region Check input data from "parameters" + if((parameters instanceof Object) == false) + return Promise.reject("The \"parameters\" must has \"Object\" type"); + + if(("checkIntegrity" in parameters) == false) + parameters.checkIntegrity = true; + // #endregion + + // #region Initial variables + var _this = this; + var sequence = Promise.resolve(); + // #endregion + + // #region Get a "crypto" extension + var crypto = in_window.org.pkijs.getCrypto(); + if(typeof crypto == "undefined") + return Promise.reject("Unable to create WebCrypto object"); + // #endregion + + // #region Create value for "this.parsedValue.authenticatedSafe" and check integrity + this.parsedValue = {}; + + switch(this.authSafe.contentType) + { + // #region data + case "1.2.840.113549.1.7.1": + { + // #region Check additional mandatory parameters + if(("password" in parameters) == false) + return Promise.reject("Absent mandatory parameter \"password\""); + // #endregion + + // #region Integrity based on HMAC + this.parsedValue.integrityMode = 0; + // #endregion + + // #region Check that we do have OCTETSTRING as "content" + if((this.authSafe.content instanceof in_window.org.pkijs.asn1.OCTETSTRING) == false) + return Promise.reject("Wrong type of \"this.authSafe.content\""); + // #endregion + + // #region Parse internal ASN.1 data + var asn1 = in_window.org.pkijs.fromBER(this.authSafe.content.value_block.value_hex); + if(asn1.offset == (-1)) + return Promise.reject("Error during parsing of ASN.1 data inside \"this.authSafe.content\""); + // #endregion + + // #region Set "authenticatedSafe" value + this.parsedValue.authenticatedSafe = new in_window.org.pkijs.simpl.pkcs12.AuthenticatedSafe({ schema: asn1.result }); + // #endregion + + // #region Check integrity + if(parameters.checkIntegrity) + { + // #region Check that "MacData" exists + if(("macData" in _this) == false) + return Promise.reject("Absent \"macData\" value, can not check PKCS# data integrity"); + // #endregion + + // #region Initial variables + var hashAlgorithm = in_window.org.pkijs.getAlgorithmByOID(_this.macData.mac.digestAlgorithm.algorithm_id); + if(("name" in hashAlgorithm) === false) + return Promise.reject("Unsupported digest algorithm: " + _this.macData.mac.digestAlgorithm.algorithm_id); + + var length; + + // #region Choose correct length for HMAC key + switch(hashAlgorithm.name.toLowerCase()) + { + case "sha-1": + length = 160; + break; + case "sha-256": + length = 256; + break; + case "sha-384": + length = 384; + break; + case "sha-512": + length = 512; + break; + default: + return Promise.reject("Incorrect \"hashAlgorithm\": " + hashAlgorithm.name); + } + // #endregion + + var hmacAlgorithm = { + name: "HMAC", + length: length, + hash: { + name: hashAlgorithm.name + } + }; + // #endregion + + // #region Generate HMAC key using PBKDF2 + // #region Derive PBKDF2 key from "password" buffer + sequence = sequence.then( + function(result) + { + var passwordView = new Uint8Array(parameters.password); + + return crypto.importKey("raw", + passwordView, + "PBKDF2", + true, + ['deriveKey']); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + // #region Derive key for HMAC + sequence = sequence.then( + function(result) + { + return crypto.deriveKey({ + name: "PBKDF2", + hash: { + name: hashAlgorithm.name + }, + salt: new Uint8Array(_this.macData.macSalt.value_block.value_hex), + iterations: _this.macData.iterations + }, + result, + hmacAlgorithm, + true, + ['verify']); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + // #endregion + + // #region Verify HMAC signature + sequence = sequence.then( + function(result) + { + var data = _this.authSafe.content.toBER(false); + var view = new Uint8Array(data); + + return crypto.verify(hmacAlgorithm, + result, + new Uint8Array(_this.macData.mac.digest.value_block.value_hex), + view); + }, + function(error) + { + return Promise.reject(error); + } + ); + + sequence = sequence.then( + function(result) + { + if(result == false) + return Promise.reject("Integrity for the PKCS#12 data is broken!"); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + } + // #endregion + } + break; + // #endregion + // #region signedData + case "1.2.840.113549.1.7.2": + { + // #region Integrity based on signature using public key + this.parsedValue.integrityMode = 1; + // #endregion + + // #region Parse CMS Signed Data + var cms_signed_simpl = new in_window.org.pkijs.simpl.CMS_SIGNED_DATA({ schema: this.authSafe.content }); + // #endregion + + // #region Check that we do have OCTETSTRING as "content" + if(("eContent" in cms_signed_simpl.encapContentInfo) == false) + return Promise.reject("Absent of attached data in \"cms_signed_simpl.encapContentInfo\""); + + if((cms_signed_simpl.encapContentInfo.eContent instanceof in_window.org.pkijs.asn1.OCTETSTRING) == false) + return Promise.reject("Wrong type of \"cms_signed_simpl.encapContentInfo.eContent\""); + // #endregion + + // #region Create correct data block for verification + var data = new ArrayBuffer(0); + + if(cms_signed_simpl.encapContentInfo.eContent.id_block.is_constructed == false) + data = cms_signed_simpl.encapContentInfo.eContent.value_block.value_hex; + else + { + for(var i = 0; i < cms_signed_simpl.encapContentInfo.eContent.value_block.value.length; i++) + data = in_window.org.pkijs.concat_buffers(data, cms_signed_simpl.encapContentInfo.eContent.value_block.value[i].value_block.value_hex); + } + // #endregion + + // #region Parse internal ASN.1 data + var asn1 = in_window.org.pkijs.fromBER(data); + if(asn1.offset == (-1)) + return Promise.reject("Error during parsing of ASN.1 data inside \"this.authSafe.content\""); + // #endregion + + // #region Set "authenticatedSafe" value + this.parsedValue.authenticatedSafe = new in_window.org.pkijs.simpl.pkcs12.AuthenticatedSafe({ schema: asn1.result }); + // #endregion + + // #region Check integrity + sequence = sequence.then( + function() + { + return cms_signed_simpl.verify({ signer: 0, checkChain: false }); + } + ).then( + function(result) + { + if(result == false) + return Promise.reject("Integrity for the PKCS#12 data is broken!"); + }, + function(error) + { + return Promise.reject("Error during integrity verification: " + error); + } + ); + // #endregion + } + break; + // #endregion + // #region default + default: + return Promise.reject("Incorrect value for \"this.authSafe.contentType\": " + _this.authSafe.contentType); + // #endregion + } + // #endregion + + // #region Return result of the function + return sequence.then( + function(result) + { + return _this; + }, + function(error) + { + return Promise.reject("Error during parsing: " + error); + } + ); + // #endregion + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "AuthenticatedSafe" type + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.AuthenticatedSafe = + function() + { + // #region Internal properties of the object + this.safeContents = new Array(); // Array of "in_window.org.pkijs.simpl.CMS_CONTENT_INFO" + + // OPTIONAL this.parsedValue = {}; // Object having all parsed data from initial "safeContents" + // #endregion + + // #region Initialize internal properties based on input data + if(arguments[0] instanceof Object) + { + switch(true) + { + case ("schema" in arguments[0]): + in_window.org.pkijs.simpl.pkcs12.AuthenticatedSafe.prototype.fromSchema.call(this, arguments[0].schema); + break; + default: + this.safeContents = (arguments[0].safeContents || new Array()); + + if("parsedValue" in arguments[0]) + this.parsedValue = arguments[0].parsedValue; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.AuthenticatedSafe.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.pkcs12.AuthenticatedSafe({ + names: { + contentInfos: "contentInfos" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for AuthenticatedSafe"); + // #endregion + + // #region Get internal properties from parsed schema + for(var i = 0; i < asn1.result["contentInfos"].length; i++) + this.safeContents.push(new in_window.org.pkijs.simpl.CMS_CONTENT_INFO({ schema: (asn1.result["contentInfos"])[i] })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.AuthenticatedSafe.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + var output_array = new Array(); + + for(var i = 0; i < this.safeContents.length; i++) + output_array.push(this.safeContents[i].toSchema()); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.AuthenticatedSafe.prototype.toJSON = + function() + { + var output = { + contentInfos: new Array() + }; + + for(var i = 0; i < this.safeContents.length; i++) + output.contentInfos.push(this.safeContents[i].toJSON()); + + return output; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.AuthenticatedSafe.prototype.parseInternalValues = + function(parameters) + { + // #region Check input data from "parameters" + if((parameters instanceof Object) == false) + return Promise.reject("The \"parameters\" must has \"Object\" type"); + + if(("safeContents" in parameters) == false) + return Promise.reject("Absent mandatory parameter \"safeContents\""); + + if((parameters.safeContents instanceof Array) == false) + return Promise.reject("The \"parameters.safeContents\" must has \"Array\" type"); + + if(parameters.safeContents.length != this.safeContents.length) + return Promise.reject("Length of \"parameters.safeContents\" must be equal to \"this.safeContents.length\""); + // #endregion + + // #region Initial variables + var _this = this; + var sequence = Promise.resolve(); + + var _safeContents = _this.safeContents.slice(); + // #endregion + + // #region Create value for "this.parsedValue.authenticatedSafe" + _this.parsedValue = { + safeContents: new Array() + }; + + for(var j = 0; j < _this.safeContents.length; j++) + { + switch(_this.safeContents[j].contentType) + { + // #region data + case "1.2.840.113549.1.7.1": + { + // #region Check that we do have OCTETSTRING as "content" + if((_this.safeContents[j].content instanceof in_window.org.pkijs.asn1.OCTETSTRING) == false) + return Promise.reject("Wrong type of \"this.safeContents[j].content\""); + // #endregion + + // #region Parse internal ASN.1 data + var asn1 = in_window.org.pkijs.fromBER(_this.safeContents[j].content.value_block.value_hex); + if(asn1.offset == (-1)) + return Promise.reject("Error during parsing of ASN.1 data inside \"_this.safeContents[j].content\""); + // #endregion + + // #region Finilly initialize initial values of "SafeContents" type + _this.parsedValue.safeContents.push({ + privacyMode: 0, // No privacy, clear data + value: new in_window.org.pkijs.simpl.pkcs12.SafeContents({ schema: asn1.result }) + }); + // #endregion + } + break; + // #endregion + // #region envelopedData + case "1.2.840.113549.1.7.3": + { + // #region Initial variables + var cms_enveloped_simp = new in_window.org.pkijs.simpl.CMS_ENVELOPED_DATA({ schema: _this.safeContents[j].content }); + // #endregion + + // #region Check mandatory parameters + if(("recipientCertificate" in parameters.safeContents[j]) == false) + return Promise.reject("Absent mandatory parameter \"recipientCertificate\" in \"parameters.safeContents[j]\""); + + var recipientCertificate = parameters.safeContents[j].recipientCertificate; + + if(("recipientKey" in parameters.safeContents[j]) == false) + return Promise.reject("Absent mandatory parameter \"recipientKey\" in \"parameters.safeContents[j]\""); + + var recipientKey = parameters.safeContents[j].recipientKey; + // #endregion + + // #region Decrypt CMS EnvelopedData using first recipient information + sequence = sequence.then( + function() + { + return cms_enveloped_simp.decrypt(0, { + recipientCertificate: recipientCertificate, + recipientPrivateKey: recipientKey + }); + } + ); + + sequence = sequence.then( + function(result) + { + var asn1 = in_window.org.pkijs.fromBER(result); + if(asn1.offset == (-1)) + return Promise.reject("Error during parsing of decrypted data"); + + _this.parsedValue.safeContents.push({ + privacyMode: 2, // Public-key privacy mode + value: new in_window.org.pkijs.simpl.pkcs12.SafeContents({ schema: asn1.result }) + }); + } + ); + // #endregion + } + break; + // #endregion + // #region encryptedData + case "1.2.840.113549.1.7.6": + { + // #region Initial variables + var cms_encrypted_simpl = new in_window.org.pkijs.simpl.CMS_ENCRYPTED_DATA({ schema: _this.safeContents[j].content }); + // #endregion + + // #region Check mandatory parameters + if(("password" in parameters.safeContents[j]) == false) + return Promise.reject("Absent mandatory parameter \"password\" in \"parameters.safeContents[j]\""); + + var password = parameters.safeContents[j].password; + // #endregion + + // #region Decrypt CMS EncryptedData using password + sequence = sequence.then( + function(result) + { + return cms_encrypted_simpl.decrypt({ + password: password + }); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + // #region Initialize internal data + sequence = sequence.then( + function(result) + { + var asn1 = in_window.org.pkijs.fromBER(result); + if(asn1.offset == (-1)) + return Promise.reject("Error during parsing of decrypted data"); + + _this.parsedValue.safeContents.push({ + privacyMode: 1, // Password-based privacy mode + value: new in_window.org.pkijs.simpl.pkcs12.SafeContents({ schema: asn1.result }) + }); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + } + break; + // #endregion + // #region default + default: + throw new Error("Unknown \"contentType\" for AuthenticatedSafe: " + contentInfo.contentType); + // #endregion + } + }; + // #endregion + + return sequence; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.AuthenticatedSafe.prototype.makeInternalValues = + function(parameters) + { + // #region Check data in "parsedValue" + if(("parsedValue" in this) == false) + return Promise.reject("Please run \"parseValues\" first or add \"parsedValue\" manually"); + + if((this.parsedValue instanceof Object) == false) + return Promise.reject("The \"this.parsedValue\" must has \"Object\" type"); + + if((this.parsedValue.safeContents instanceof Array) == false) + return Promise.reject("The \"this.parsedValue.safeContents\" must has \"Array\" type"); + // #endregion + + // #region Check input data from "parameters" + if((parameters instanceof Object) == false) + return Promise.reject("The \"parameters\" must has \"Object\" type"); + + if(("safeContents" in parameters) == false) + return Promise.reject("Absent mandatory parameter \"safeContents\""); + + if((parameters.safeContents instanceof Array) == false) + return Promise.reject("The \"parameters.safeContents\" must has \"Array\" type"); + + if(parameters.safeContents.length != this.parsedValue.safeContents.length) + return Promise.reject("Length of \"parameters.safeContents\" must be equal to \"this.parsedValue.safeContents\""); + // #endregion + + // #region Initial variables + var _this = this; + var sequence = Promise.resolve(); + + var promises = new Array(); + // #endregion + + // #region Create internal values from already parsed values + _this.safeContents = new Array(); + + for(var i = 0; i < _this.parsedValue.safeContents.length; i++) + { + // #region Check current "_this.parsedValue.safeContents[i]" value + if(("privacyMode" in _this.parsedValue.safeContents[i]) == false) + return Promise.reject("The \"privacyMode\" is a mandatory parameter for \"_this.parsedValue.safeContents[i]\""); + + if(("value" in _this.parsedValue.safeContents[i]) == false) + return Promise.reject("The \"value\" is a mandatory parameter for \"_this.parsedValue.safeContents[i]\""); + + if((_this.parsedValue.safeContents[i].value instanceof in_window.org.pkijs.simpl.pkcs12.SafeContents) == false) + return Promise.reject("The \"_this.parsedValue.safeContents[i].value\" must has \"in_window.org.pkijs.simpl.pkcs12.SafeContents\" type"); + // #endregion + + switch(_this.parsedValue.safeContents[i].privacyMode) + { + // #region No privacy + case 0: + { + var content = _this.parsedValue.safeContents[i].value.toSchema().toBER(false); + + sequence = sequence.then( + function() + { + _this.safeContents.push(new in_window.org.pkijs.simpl.CMS_CONTENT_INFO({ + contentType: "1.2.840.113549.1.7.1", + content: new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: content }) + })); + }); + } + break; + // #endregion + // #region Privacy with password + case 1: + { + // #region Initial variables + var cms_encrypted_simp = new in_window.org.pkijs.simpl.CMS_ENCRYPTED_DATA(); + + var currentParameters = parameters.safeContents[i]; + currentParameters.contentToEncrypt = _this.parsedValue.safeContents[i].value.toSchema().toBER(false); + // #endregion + + // #region Encrypt CMS EncryptedData using password + sequence = sequence.then( + function() + { + return cms_encrypted_simp.encrypt(currentParameters); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + // #region Store result content in CMS_CONTENT_INFO type + sequence = sequence.then( + function(result) + { + _this.safeContents.push(new in_window.org.pkijs.simpl.CMS_CONTENT_INFO({ + contentType: "1.2.840.113549.1.7.6", + content: cms_encrypted_simp.toSchema() + })); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + } + break; + // #endregion + // #region Privacy with public key + case 2: + { + // #region Initial variables + var cmsEnveloped = new in_window.org.pkijs.simpl.CMS_ENVELOPED_DATA(); + var contentToEncrypt = _this.parsedValue.safeContents[i].value.toSchema().toBER(false); + // #endregion + + // #region Check mandatory parameters + if(("encryptingCertificate" in parameters.safeContents[i]) == false) + return Promise.reject("Absent mandatory parameter \"encryptingCertificate\" in \"parameters.safeContents[i]\""); + + if(("encryptionAlgorithm" in parameters.safeContents[i]) == false) + return Promise.reject("Absent mandatory parameter \"encryptionAlgorithm\" in \"parameters.safeContents[i]\""); + + switch(true) + { + case (parameters.safeContents[i].encryptionAlgorithm.name.toLowerCase() == "aes-cbc"): + case (parameters.safeContents[i].encryptionAlgorithm.name.toLowerCase() == "aes-gcm"): + break; + default: + return Promise.reject("Incorrect parameter \"encryptionAlgorithm\" in \"parameters.safeContents[i]\": " + parameters.safeContents[i].encryptionAlgorithm); + } + + switch(true) + { + case (parameters.safeContents[i].encryptionAlgorithm.length == 128): + case (parameters.safeContents[i].encryptionAlgorithm.length == 192): + case (parameters.safeContents[i].encryptionAlgorithm.length == 256): + break; + default: + return Promise.reject("Incorrect parameter \"encryptionAlgorithm.length\" in \"parameters.safeContents[i]\": " + parameters.safeContents[i].encryptionAlgorithm.length); + } + // #endregion + + // #region Making correct "encryptionAlgorithm" variable + var encryptionAlgorithm = parameters.safeContents[i].encryptionAlgorithm; + // #endregion + + // #region Append recipient for enveloped data + cmsEnveloped.addRecipientByCertificate(parameters.safeContents[i].encryptingCertificate); + // #endregion + + // #region Making encryption + sequence = sequence.then( + function() + { + return cmsEnveloped.encrypt(encryptionAlgorithm, contentToEncrypt); + } + ); + + sequence = sequence.then( + function() + { + _this.safeContents.push(new in_window.org.pkijs.simpl.CMS_CONTENT_INFO({ + contentType: "1.2.840.113549.1.7.3", + content: cmsEnveloped.toSchema() + })); + } + ); + // #endregion + } + break; + // #endregion + // #region default + default: + return Promise.reject("Incorrect value for \"_this.parsedValue.safeContents[i].privacyMode\": " + _this.parsedValue.safeContents[i].privacyMode); + // #endregion + } + } + // #endregion + + // #region Return result of the function + return sequence.then( + function(result) + { + return _this; + }, + function(error) + { + return Promise.reject("Error during parsing: " + error); + } + ); + // #endregion + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "PKCS8ShroudedKeyBag" type + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.PKCS8ShroudedKeyBag = + function() + { + // #region Internal properties of the object + this.encryptionAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.encryptedData = new in_window.org.pkijs.asn1.OCTETSTRING(); + + // OPTIONAL this.parsedValue + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.pkcs12.PKCS8ShroudedKeyBag.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.encryptionAlgorithm = (arguments[0].encryptionAlgorithm || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER()); + this.encryptedData = (arguments[0].encryptedData || new in_window.org.pkijs.asn1.OCTETSTRING()); + + if("parsedValue" in arguments[0]) + this.parsedValue = arguments[0].parsedValue; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.PKCS8ShroudedKeyBag.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.pkcs12.PKCS8ShroudedKeyBag({ + names: { + encryptionAlgorithm: { + names: { + block_name: "encryptionAlgorithm" + } + }, + encryptedData: "encryptedData" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for PKCS8ShroudedKeyBag"); + // #endregion + + // #region Get internal properties from parsed schema + this.encryptionAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["encryptionAlgorithm"] }); + this.encryptedData = asn1.result["encryptedData"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.PKCS8ShroudedKeyBag.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + this.encryptionAlgorithm.toSchema(), + this.encryptedData + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.PKCS8ShroudedKeyBag.prototype.toJSON = + function() + { + return { + encryptionAlgorithm: this.encryptionAlgorithm.toJSON(), + encryptedData: this.encryptedData.toJSON() + }; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.PKCS8ShroudedKeyBag.prototype.parseInternalValues = + function(parameters) + { + // #region Initial variables + var sequence = Promise.resolve(); + var _this = this; + + var cms_encrypted_simpl = new in_window.org.pkijs.simpl.CMS_ENCRYPTED_DATA({ + encryptedContentInfo: new in_window.org.pkijs.simpl.cms.EncryptedContentInfo({ + contentEncryptionAlgorithm: this.encryptionAlgorithm, + encryptedContent: this.encryptedData + }) + }); + // #endregion + + // #region Decrypt internal data + sequence = sequence.then( + function(result) + { + return cms_encrypted_simpl.decrypt(parameters); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + // #region Initialize "parsedValue" with decrypted PKCS#8 private key + sequence = sequence.then( + function(result) + { + var asn1 = in_window.org.pkijs.fromBER(result); + if(asn1.offset == (-1)) + return Promise.reject("Error during parsing ASN.1 data"); + + _this.parsedValue = new in_window.org.pkijs.simpl.PKCS8({ schema: asn1.result }); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + return sequence; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.PKCS8ShroudedKeyBag.prototype.makeInternalValues = + function(parameters) + { + // #region Check that we do have "parsedValue" + if(("parsedValue" in this) == false) + return Promise.reject("Please initialize \"parsedValue\" first"); + // #endregion + + // #region Initial variables + var _this = this; + var sequence = Promise.resolve(); + + var cms_encrypted_simpl = new in_window.org.pkijs.simpl.CMS_ENCRYPTED_DATA(); + // #endregion + + // #region Encrypt internal data + sequence = sequence.then( + function(result) + { + parameters.contentToEncrypt = _this.parsedValue.toSchema().toBER(false); + + return cms_encrypted_simpl.encrypt(parameters); + }, + function(error) + { + return Promise.reject(error); + } + ); + // #endregion + + // #region Initialize internal values + sequence = sequence.then( + function(result) + { + _this.encryptionAlgorithm = cms_encrypted_simpl.encryptedContentInfo.contentEncryptionAlgorithm; + _this.encryptedData = cms_encrypted_simpl.encryptedContentInfo.encryptedContent; + } + ); + // #endregion + + return sequence; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "CertBag" type + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.CertBag = + function() + { + // #region Internal properties of the object + this.certId = ""; + this.certValue = new in_window.org.pkijs.asn1.ANY(); + // OPTIONAL this.parsedValue = new in_window.org.pkijs.simpl.CERT(); // In case "this.certId = 1.2.840.113549.1.9.22.1" + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.pkcs12.CertBag.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.certId = (arguments[0].certId || ""); + this.certValue = (arguments[0].certValue || new in_window.org.pkijs.asn1.ANY()); + + if("parsedValue" in arguments[0]) + this.parsedValue = arguments[0].parsedValue; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.CertBag.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.pkcs12.CertBag({ + names: { + id: "certId", + value: "certValue" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for CertBag"); + // #endregion + + // #region Get internal properties from parsed schema + this.certId = asn1.result.certId.value_block.toString(); + this.certValue = asn1.result["certValue"]; + + switch(this.certId) + { + case "1.2.840.113549.1.9.22.1": // x509Certificate + { + var asn1_cert = in_window.org.pkijs.fromBER(this.certValue.value_block.value_hex); + this.parsedValue = new in_window.org.pkijs.simpl.CERT({ schema: asn1_cert.result }); + } + break; + case "1.2.840.113549.1.9.22.2": // sdsiCertificate + default: + throw new Error("Incorrect \"certId\" value in CertBag: " + this.certId); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.CertBag.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + if("parsedValue" in this) + { + this.certId = "1.2.840.113549.1.9.22.1"; + this.certValue = new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: this.parsedValue.toSchema().toBER(false) }); + } + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + new in_window.org.pkijs.asn1.OID({ value: this.certId }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [(("toSchema" in this.certValue) ? this.certValue.toSchema() : this.certValue)] + }) + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.CertBag.prototype.toJSON = + function() + { + return { + certId: this.certId, + certValue: this.certValue.toJSON() + }; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "CRLBag" type + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.CRLBag = + function() + { + // #region Internal properties of the object + this.crlId = ""; + this.crlValue = new in_window.org.pkijs.asn1.ANY(); + + // OPTIONAL this.parsedValue = new in_window.org.pkijs.simpl.CRL(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.pkcs12.CRLBag.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.crlId = (arguments[0].crlId || ""); + this.crlValue = (arguments[0].crlValue || new in_window.org.pkijs.asn1.ANY()); + + if("parsedValue" in arguments[0]) + this.parsedValue = arguments[0].parsedValue; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.CRLBag.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.pkcs12.CRLBag({ + names: { + id: "crlId", + value: "crlValue" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for CRLBag"); + // #endregion + + // #region Get internal properties from parsed schema + this.crlId = asn1.result.crlId.value_block.toString(); + this.crlValue = asn1.result["crlValue"]; + + switch(this.crlId) + { + case "1.2.840.113549.1.9.23.1": // x509CRL + { + var asn1_cert = in_window.org.pkijs.fromBER(this.certValue.value_block.value_hex); + this.parsedValue = new in_window.org.pkijs.simpl.CRL({ schema: asn1_cert.result }); + } + break; + default: + throw new Error("Incorrect \"certId\" value in CertBag: " + this.certId); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.CRLBag.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + if("parsedValue" in this) + { + this.certId = "1.2.840.113549.1.9.23.1"; + this.certValue = new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: this.parsedValue.toSchema().toBER(false) }); + } + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + new in_window.org.pkijs.asn1.OID({ value: this.crlId }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [this.crlValue.toSchema()] + }) + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.CRLBag.prototype.toJSON = + function() + { + return { + crlId: this.crlId, + crlValue: this.crlValue.toJSON() + }; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "SecretBag" type + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.SecretBag = + function() + { + // #region Internal properties of the object + this.secretTypeId = ""; + this.secretValue = new in_window.org.pkijs.asn1.ANY(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.pkcs12.SecretBag.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.secretTypeId = (arguments[0].secretTypeId || ""); + this.secretValue = (arguments[0].secretValue || new in_window.org.pkijs.asn1.ANY()); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.SecretBag.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.pkcs12.SecretBag({ + names: { + id: "secretTypeId", + value: "secretValue" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for SecretBag"); + // #endregion + + // #region Get internal properties from parsed schema + this.secretTypeId = asn1.result.secretTypeId.value_block.toString(); + this.secretValue = asn1.result["secretValue"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.SecretBag.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + new in_window.org.pkijs.asn1.OID({ value: this.secretTypeId }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [this.secretValue.toSchema()] + }) + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.SecretBag.prototype.toJSON = + function() + { + return { + secretTypeId: this.secretTypeId, + secretValue: this.secretValue.toJSON() + }; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "SafeBag" type + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.SafeBag = + function() + { + // #region Internal properties of the object + this.bagId = ""; + this.bagValue = new in_window.org.pkijs.asn1.ANY(); + // OPTIONAL this.bagAttributes = new Array(); // Array of "in_window.org.pkijs.simpl.cms.Attribute" + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.pkcs12.SafeBag.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.bagId = (arguments[0].bagId || ""); + this.bagValue = (arguments[0].bagValue || new in_window.org.pkijs.asn1.ANY()); + + if("bagAttributes" in arguments[0]) + this.bagAttributes = arguments[0].bagAttributes; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.SafeBag.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.pkcs12.SafeBag({ + names: { + bagId: "bagId", + bagValue: "bagValue", + bagAttributes: "bagAttributes" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for SafeBag"); + // #endregion + + // #region Get internal properties from parsed schema + this.bagId = asn1.result.bagId.value_block.toString(); + + switch(this.bagId) + { + case "1.2.840.113549.1.12.10.1.1": // keyBag + this.bagValue = new in_window.org.pkijs.simpl.PKCS8({ schema: asn1.result["bagValue"] }); + break; + case "1.2.840.113549.1.12.10.1.2": // pkcs8ShroudedKeyBag + this.bagValue = new in_window.org.pkijs.simpl.pkcs12.PKCS8ShroudedKeyBag({ schema: asn1.result["bagValue"] }); + break; + case "1.2.840.113549.1.12.10.1.3": // certBag + this.bagValue = new in_window.org.pkijs.simpl.pkcs12.CertBag({ schema: asn1.result["bagValue"] }); + break; + case "1.2.840.113549.1.12.10.1.4": // crlBag + this.bagValue = new in_window.org.pkijs.simpl.pkcs12.CRLBag({ schema: asn1.result["bagValue"] }); + break; + case "1.2.840.113549.1.12.10.1.5": // secretBag + this.bagValue = new in_window.org.pkijs.simpl.pkcs12.SecretBag({ schema: asn1.result["bagValue"] }); + break; + case "1.2.840.113549.1.12.10.1.6": // safeContentsBag + this.bagValue = new in_window.org.pkijs.simpl.pkcs12.SafeContents({ schema: asn1.result["bagValue"] }); + break; + default: + throw new Error("Invalid \"bagId\" for SafeBag: " + this.bagId); + } + + if("bagAttributes" in asn1.result) + { + this.bagAttributes = new Array(); + + for(var i = 0; i < asn1.result["bagAttributes"].length; i++) + this.bagAttributes.push(new in_window.org.pkijs.simpl.cms.Attribute({ schema: (asn1.result["bagAttributes"])[i] })); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.SafeBag.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + var output_array = [ + new in_window.org.pkijs.asn1.OID({ value: this.bagId }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [this.bagValue.toSchema()] + }) + ]; + + if("bagAttributes" in this) + { + var attributesArray = new Array(); + + for(var i = 0; i < this.bagAttributes.length; i++) + attributesArray.push(this.bagAttributes[i].toSchema()); + + output_array.push(new in_window.org.pkijs.asn1.SET({ + value: attributesArray + })); + } + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.SafeBag.prototype.toJSON = + function() + { + var output = { + bagId: this.bagId, + bagValue: this.bagValue.toJSON() + }; + + if("bagAttributes" in this) + { + output.bagAttributes = new Array(); + + for(var i = 0; i < this.bagAttributes.length; i++) + output.bagAttributes.push(this.bagAttributes[i].toJSON()); + } + + return output; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "SafeContents" type + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.SafeContents = + function() + { + // #region Internal properties of the object + this.safeBags = new Array(); // Array of "in_window.org.pkijs.simpl.pkcs12.SafeBag" + // #endregion + + // #region Initialize internal properties based on input data + if(arguments[0] instanceof Object) + { + switch(true) + { + case ("schema" in arguments[0]): + in_window.org.pkijs.simpl.pkcs12.SafeContents.prototype.fromSchema.call(this, arguments[0].schema); + break; + case ("contentInfo" in arguments[0]): + in_window.org.pkijs.simpl.pkcs12.SafeContents.prototype.fromContentInfo.call(this, arguments[0].contentInfo); + break; + default: + this.safeBags = (arguments[0].safeBags || new Array()); + + this.privacyMode = (arguments[0].privacyMode || 0); + this.privacyParameters = (arguments[0].privacyParameters || {}); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.SafeContents.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.pkcs12.SafeContents({ + names: { + safeBags: "safeBags" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for SafeContents"); + // #endregion + + // #region Get internal properties from parsed schema + for(var i = 0; i < asn1.result["safeBags"].length; i++) + this.safeBags.push(new in_window.org.pkijs.simpl.pkcs12.SafeBag({ schema: (asn1.result["safeBags"])[i] })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.SafeContents.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + var output_array = new Array(); + + for(var i = 0; i < this.safeBags.length; i++) + output_array.push(this.safeBags[i].toSchema()); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.pkcs12.SafeContents.prototype.toJSON = + function() + { + var output = { + safeBags: new Array() + }; + + for(var i = 0; i < this.safeBags.length; i++) + output.safeBags.push(this.safeBags[i].toJSON()); + + return output; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** +} +)(typeof exports !== "undefined" ? exports : window); \ No newline at end of file diff --git a/express-server/node_modules/pkijs/org/pkijs/x509_schema.js b/express-server/node_modules/pkijs/org/pkijs/x509_schema.js new file mode 100644 index 00000000..f8d71fae --- /dev/null +++ b/express-server/node_modules/pkijs/org/pkijs/x509_schema.js @@ -0,0 +1,1889 @@ +/* + * Copyright (c) 2014, GMO GlobalSign + * Copyright (c) 2015, Peculiar Ventures + * All rights reserved. + * + * Author 2014-2015, Yury Strozhevsky . + * + * 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 copyright holder 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. + * + */ +( +function(in_window) +{ + //************************************************************************************** + // #region Declaration of global variables + //************************************************************************************** + // #region "org" namespace + if(typeof in_window.org === "undefined") + in_window.org = {}; + else + { + if(typeof in_window.org !== "object") + throw new Error("Name org already exists and it's not an object"); + } + // #endregion + + // #region "org.pkijs" namespace + if(typeof in_window.org.pkijs === "undefined") + in_window.org.pkijs = {}; + else + { + if(typeof in_window.org.pkijs !== "object") + throw new Error("Name org.pkijs already exists and it's not an object" + " but " + (typeof in_window.org.pkijs)); + } + // #endregion + + // #region "org.pkijs.schema" namespace + if(typeof in_window.org.pkijs.schema === "undefined") + in_window.org.pkijs.schema = {}; + else + { + if(typeof in_window.org.pkijs.schema !== "object") + throw new Error("Name org.pkijs.schema already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.schema)); + } + // #endregion + + // #region "org.pkijs.schema.x509" namespace + if(typeof in_window.org.pkijs.schema.x509 === "undefined") + in_window.org.pkijs.schema.x509 = {}; + else + { + if(typeof in_window.org.pkijs.schema.x509 !== "object") + throw new Error("Name org.pkijs.schema.x509 already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.schema.x509)); + } + // #endregion + + // #region "local" namespace + var local = {}; + // #endregion + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "Time" type + //************************************************************************************** + in_window.org.pkijs.schema.TIME = + function(input_names, input_optional) + { + var names = in_window.org.pkijs.getNames(arguments[0]); + var optional = (input_optional || false); + + return (new in_window.org.pkijs.asn1.CHOICE({ + optional: optional, + value: [ + new in_window.org.pkijs.asn1.UTCTIME({ name: (names.utcTimeName || "") }), + new in_window.org.pkijs.asn1.GENERALIZEDTIME({ name: (names.generalTimeName || "") }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for X.509 v3 certificate (RFC5280) + //************************************************************************************** + local.tbsCertificate = + function() + { + //TBSCertificate ::= SEQUENCE { + // version [0] EXPLICIT Version DEFAULT v1, + // serialNumber CertificateSerialNumber, + // signature AlgorithmIdentifier, + // issuer Name, + // validity Validity, + // subject Name, + // subjectPublicKeyInfo SubjectPublicKeyInfo, + // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + // -- If present, version MUST be v2 or v3 + // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + // -- If present, version MUST be v2 or v3 + // extensions [3] EXPLICIT Extensions OPTIONAL + // -- If present, version MUST be v3 + //} + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || "tbsCertificate"), + value: [ + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [ + new in_window.org.pkijs.asn1.INTEGER({ name: (names.tbsCertificate_version || "tbsCertificate.version") }) // EXPLICIT integer value + ] + }), + new in_window.org.pkijs.asn1.INTEGER({ name: (names.tbsCertificate_serialNumber || "tbsCertificate.serialNumber") }), + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.signature || { + names: { + block_name: "tbsCertificate.signature" + } + }), + in_window.org.pkijs.schema.RDN(names.issuer || { + names: { + block_name: "tbsCertificate.issuer" + } + }), + new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.tbsCertificate_validity || "tbsCertificate.validity"), + value: [ + in_window.org.pkijs.schema.TIME(names.not_before || { + names: { + utcTimeName: "tbsCertificate.notBefore", + generalTimeName: "tbsCertificate.notBefore" + } + }), + in_window.org.pkijs.schema.TIME(names.not_after || { + names: { + utcTimeName: "tbsCertificate.notAfter", + generalTimeName: "tbsCertificate.notAfter" + } + }) + ] + }), + in_window.org.pkijs.schema.RDN(names.subject || { + names: { + block_name: "tbsCertificate.subject" + } + }), + in_window.org.pkijs.schema.PUBLIC_KEY_INFO(names.subjectPublicKeyInfo || { + names: { + block_name: "tbsCertificate.subjectPublicKeyInfo" + } + }), + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + name: (names.tbsCertificate_issuerUniqueID ||"tbsCertificate.issuerUniqueID"), + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + } + }), // IMPLICIT bistring value + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + name: (names.tbsCertificate_subjectUniqueID ||"tbsCertificate.subjectUniqueID"), + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 2 // [2] + } + }), // IMPLICIT bistring value + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 3 // [3] + }, + value: [in_window.org.pkijs.schema.EXTENSIONS(names.extensions || { + names: { + block_name: "tbsCertificate.extensions" + } + })] + }) // EXPLICIT SEQUENCE value + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.CERT = + function() + { + //Certificate ::= SEQUENCE { + // tbsCertificate TBSCertificate, + // signatureAlgorithm AlgorithmIdentifier, + // signatureValue BIT STRING } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + local.tbsCertificate(names.tbsCertificate), + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.signatureAlgorithm || { + names: { + block_name: "signatureAlgorithm" + } + }), + new in_window.org.pkijs.asn1.BITSTRING({ name: (names.signatureValue || "signatureValue") }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for X.509 CRL (Certificate Revocation List)(RFC5280) + //************************************************************************************** + local.tbsCertList = + function() + { + //TBSCertList ::= SEQUENCE { + // version Version OPTIONAL, + // -- if present, MUST be v2 + // signature AlgorithmIdentifier, + // issuer Name, + // thisUpdate Time, + // nextUpdate Time OPTIONAL, + // revokedCertificates SEQUENCE OF SEQUENCE { + // userCertificate CertificateSerialNumber, + // revocationDate Time, + // crlEntryExtensions Extensions OPTIONAL + // -- if present, version MUST be v2 + // } OPTIONAL, + // crlExtensions [0] EXPLICIT Extensions OPTIONAL + // -- if present, version MUST be v2 + //} + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || "tbsCertList"), + value: [ + new in_window.org.pkijs.asn1.INTEGER({ + optional: true, + name: (names.tbsCertList_version || "tbsCertList.version"), + value: 2 + }), // EXPLICIT integer value (v2) + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.signature || { + names: { + block_name: "tbsCertList.signature" + } + }), + in_window.org.pkijs.schema.RDN(names.issuer || { + names: { + block_name: "tbsCertList.issuer" + } + }), + in_window.org.pkijs.schema.TIME(names.tbsCertList_thisUpdate || { + names: { + utcTimeName: "tbsCertList.thisUpdate", + generalTimeName: "tbsCertList.thisUpdate" + } + }), + in_window.org.pkijs.schema.TIME(names.tbsCertList_nextUpdate || { + names: { + utcTimeName: "tbsCertList.nextUpdate", + generalTimeName: "tbsCertList.nextUpdate" + } + }, true), + new in_window.org.pkijs.asn1.SEQUENCE({ + optional: true, + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.tbsCertList_revokedCertificates || "tbsCertList.revokedCertificates"), + value: new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + new in_window.org.pkijs.asn1.INTEGER(), + in_window.org.pkijs.schema.TIME(), + in_window.org.pkijs.schema.EXTENSIONS({}, true) + ] + }) + }) + ] + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [in_window.org.pkijs.schema.EXTENSIONS(names.crlExtensions || { + names: { + block_name: "tbsCertList.extensions" + } + })] + }) // EXPLICIT SEQUENCE value + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.CRL = + function() + { + //CertificateList ::= SEQUENCE { + // tbsCertList TBSCertList, + // signatureAlgorithm AlgorithmIdentifier, + // signatureValue BIT STRING } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || "CertificateList"), + value: [ + local.tbsCertList(arguments[0]), + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.signatureAlgorithm || { + names: { + block_name: "signatureAlgorithm" + } + }), + new in_window.org.pkijs.asn1.BITSTRING({ name: (names.signatureValue || "signatureValue") }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for PKCS#10 certificate request + //************************************************************************************** + local.CertificationRequestInfo = + function() + { + //CertificationRequestInfo ::= SEQUENCE { + // version INTEGER { v1(0) } (v1,...), + // subject Name, + // subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }}, + // attributes [0] Attributes{{ CRIAttributes }} + //} + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.CertificationRequestInfo || "CertificationRequestInfo"), + value: [ + new in_window.org.pkijs.asn1.INTEGER({ name: (names.CertificationRequestInfo_version || "CertificationRequestInfo.version") }), + new in_window.org.pkijs.schema.RDN(names.subject || { + names: { + block_name: "CertificationRequestInfo.subject" + } + }), + new in_window.org.pkijs.schema.PUBLIC_KEY_INFO({ + names: { + block_name: "CertificationRequestInfo.subjectPublicKeyInfo" + } + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + optional: true, // Because OpenSSL makes wrong "attributes" field + name: (names.CertificationRequestInfo_attributes || "CertificationRequestInfo.attributes"), + value: in_window.org.pkijs.schema.ATTRIBUTE(names.attributes || {}) + }) + ] + }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.PKCS10 = + function() + { + //CertificationRequest ::= SEQUENCE { + // certificationRequestInfo CertificationRequestInfo, + // signatureAlgorithm AlgorithmIdentifier{{ SignatureAlgorithms }}, + // signature BIT STRING + //} + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + local.CertificationRequestInfo(names.certificationRequestInfo || {}), + new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.signatureAlgorithm || "signatureAlgorithm"), + value: [ + new in_window.org.pkijs.asn1.OID(), + new in_window.org.pkijs.asn1.ANY({ optional: true }) + ] + }), + new in_window.org.pkijs.asn1.BITSTRING({ name: (names.signatureValue || "signatureValue") }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for PKCS#8 private key bag + //************************************************************************************** + in_window.org.pkijs.schema.PKCS8 = + function() + { + //PrivateKeyInfo ::= SEQUENCE { + // version Version, + // privateKeyAlgorithm AlgorithmIdentifier {{PrivateKeyAlgorithms}}, + // privateKey PrivateKey, + // attributes [0] Attributes OPTIONAL } + // + //Version ::= INTEGER {v1(0)} (v1,...) + // + //PrivateKey ::= OCTET STRING + // + //Attributes ::= SET OF Attribute + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + new in_window.org.pkijs.asn1.INTEGER({ name: (names.version || "") }), + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.privateKeyAlgorithm || ""), + new in_window.org.pkijs.asn1.OCTETSTRING({ name: (names.privateKey || "") }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.attributes || ""), + value: in_window.org.pkijs.schema.ATTRIBUTE() + }) + ] + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "GeneralName" type + //************************************************************************************** + local.BuiltInStandardAttributes = + function(optional_flag) + { + //BuiltInStandardAttributes ::= SEQUENCE { + // country-name CountryName OPTIONAL, + // administration-domain-name AdministrationDomainName OPTIONAL, + // network-address [0] IMPLICIT NetworkAddress OPTIONAL, + // terminal-identifier [1] IMPLICIT TerminalIdentifier OPTIONAL, + // private-domain-name [2] PrivateDomainName OPTIONAL, + // organization-name [3] IMPLICIT OrganizationName OPTIONAL, + // numeric-user-identifier [4] IMPLICIT NumericUserIdentifier OPTIONAL, + // personal-name [5] IMPLICIT PersonalName OPTIONAL, + // organizational-unit-names [6] IMPLICIT OrganizationalUnitNames OPTIONAL } + + if(typeof optional_flag === "undefined") + optional_flag = false; + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + optional: optional_flag, + value: [ + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 2, // APPLICATION-SPECIFIC + tag_number: 1 // [1] + }, + name: (names.country_name || ""), + value: [ + new in_window.org.pkijs.asn1.CHOICE({ + value: [ + new in_window.org.pkijs.asn1.NUMERICSTRING(), + new in_window.org.pkijs.asn1.PRINTABLESTRING() + ] + }) + ] + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 2, // APPLICATION-SPECIFIC + tag_number: 2 // [2] + }, + name: (names.administration_domain_name || ""), + value: [ + new in_window.org.pkijs.asn1.CHOICE({ + value: [ + new in_window.org.pkijs.asn1.NUMERICSTRING(), + new in_window.org.pkijs.asn1.PRINTABLESTRING() + ] + }) + ] + }), + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + name: (names.network_address || ""), + is_hex_only: true + }), + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + name: (names.terminal_identifier || ""), + is_hex_only: true + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 2 // [2] + }, + name: (names.private_domain_name || ""), + value: [ + new in_window.org.pkijs.asn1.CHOICE({ + value: [ + new in_window.org.pkijs.asn1.NUMERICSTRING(), + new in_window.org.pkijs.asn1.PRINTABLESTRING() + ] + }) + ] + }), + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 3 // [3] + }, + name: (names.organization_name || ""), + is_hex_only: true + }), + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + optional: true, + name: (names.numeric_user_identifier || ""), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 4 // [4] + }, + is_hex_only: true + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + name: (names.personal_name || ""), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 5 // [5] + }, + value: [ + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + is_hex_only: true + }), + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + is_hex_only: true + }), + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 2 // [2] + }, + is_hex_only: true + }), + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 3 // [3] + }, + is_hex_only: true + }) + ] + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + name: (names.organizational_unit_names || ""), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 6 // [6] + }, + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + value: new in_window.org.pkijs.asn1.PRINTABLESTRING() + }) + ] + }) + ] + })); + }; + //************************************************************************************** + local.BuiltInDomainDefinedAttributes = + function(optional_flag) + { + if(typeof optional_flag === "undefined") + optional_flag = false; + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + optional: optional_flag, + value: [ + new in_window.org.pkijs.asn1.PRINTABLESTRING(), + new in_window.org.pkijs.asn1.PRINTABLESTRING() + ] + })); + }; + //************************************************************************************** + local.ExtensionAttributes = + function(optional_flag) + { + if(typeof optional_flag === "undefined") + optional_flag = false; + + return (new in_window.org.pkijs.asn1.SET({ + optional: optional_flag, + value: [ + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + is_hex_only: true + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [new in_window.org.pkijs.asn1.ANY()] + }) + ] + })); + }; + //************************************************************************************** + in_window.org.pkijs.schema.GENERAL_NAME = + function() + { + /// By passing "names" array as an argument you can name each element of "GENERAL NAME" choice + + //GeneralName ::= CHOICE { + // otherName [0] OtherName, + // rfc822Name [1] IA5String, + // dNSName [2] IA5String, + // x400Address [3] ORAddress, + // directoryName [4] Name, + // ediPartyName [5] EDIPartyName, + // uniformResourceIdentifier [6] IA5String, + // iPAddress [7] OCTET STRING, + // registeredID [8] OBJECT IDENTIFIER } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.CHOICE({ + value: [ + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.OID(), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [new in_window.org.pkijs.asn1.ANY()] + }) + ] + }), + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + name: (names.block_name || ""), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + } + }), + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + name: (names.block_name || ""), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 2 // [2] + } + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 3 // [3] + }, + name: (names.block_name || ""), + value: [ + local.BuiltInStandardAttributes(false), + local.BuiltInDomainDefinedAttributes(true), + local.ExtensionAttributes(true) + ] + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 4 // [4] + }, + name: (names.block_name || ""), + value: [in_window.org.pkijs.schema.RDN(names.directoryName || {})] + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 5 // [5] + }, + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [ + new in_window.org.pkijs.asn1.CHOICE({ + value: [ + new in_window.org.pkijs.asn1.TELETEXSTRING(), + new in_window.org.pkijs.asn1.PRINTABLESTRING(), + new in_window.org.pkijs.asn1.UNIVERSALSTRING(), + new in_window.org.pkijs.asn1.UTF8STRING(), + new in_window.org.pkijs.asn1.BMPSTRING() + ] + }) + ] + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [ + new in_window.org.pkijs.asn1.CHOICE({ + value: [ + new in_window.org.pkijs.asn1.TELETEXSTRING(), + new in_window.org.pkijs.asn1.PRINTABLESTRING(), + new in_window.org.pkijs.asn1.UNIVERSALSTRING(), + new in_window.org.pkijs.asn1.UTF8STRING(), + new in_window.org.pkijs.asn1.BMPSTRING() + ] + }) + ] + }) + ] + }), + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + name: (names.block_name || ""), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 6 // [6] + } + }), + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + name: (names.block_name || ""), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 7 // [7] + } + }), + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + name: (names.block_name || ""), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 8 // [8] + } + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "AlgorithmIdentifier" type + //************************************************************************************** + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER = + function() + { + //AlgorithmIdentifier ::= SEQUENCE { + // algorithm OBJECT IDENTIFIER, + // parameters ANY DEFINED BY algorithm OPTIONAL } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + optional: (names.optional || false), + value: [ + new in_window.org.pkijs.asn1.OID({ name: (names.algorithmIdentifier || "") }), + new in_window.org.pkijs.asn1.ANY({ name: (names.algorithmParams || ""), optional: true }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "RSAPublicKey" type (RFC3447) + //************************************************************************************** + in_window.org.pkijs.schema.x509.RSAPublicKey = + function() + { + //RSAPublicKey ::= SEQUENCE { + // modulus INTEGER, -- n + // publicExponent INTEGER -- e + //} + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.INTEGER({ name: (names.modulus || "") }), + new in_window.org.pkijs.asn1.INTEGER({ name: (names.publicExponent || "") }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "OtherPrimeInfo" type (RFC3447) + //************************************************************************************** + in_window.org.pkijs.schema.x509.OtherPrimeInfo = + function() + { + //OtherPrimeInfo ::= SEQUENCE { + // prime INTEGER, -- ri + // exponent INTEGER, -- di + // coefficient INTEGER -- ti + //} + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.INTEGER({ name: (names.prime || "") }), + new in_window.org.pkijs.asn1.INTEGER({ name: (names.exponent || "") }), + new in_window.org.pkijs.asn1.INTEGER({ name: (names.coefficient || "") }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "RSAPrivateKey" type (RFC3447) + //************************************************************************************** + in_window.org.pkijs.schema.x509.RSAPrivateKey = + function() + { + //RSAPrivateKey ::= SEQUENCE { + // version Version, + // modulus INTEGER, -- n + // publicExponent INTEGER, -- e + // privateExponent INTEGER, -- d + // prime1 INTEGER, -- p + // prime2 INTEGER, -- q + // exponent1 INTEGER, -- d mod (p-1) + // exponent2 INTEGER, -- d mod (q-1) + // coefficient INTEGER, -- (inverse of q) mod p + // otherPrimeInfos OtherPrimeInfos OPTIONAL + //} + // + //OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.INTEGER({ name: (names.version || "") }), + new in_window.org.pkijs.asn1.INTEGER({ name: (names.modulus || "") }), + new in_window.org.pkijs.asn1.INTEGER({ name: (names.publicExponent || "") }), + new in_window.org.pkijs.asn1.INTEGER({ name: (names.privateExponent || "") }), + new in_window.org.pkijs.asn1.INTEGER({ name: (names.prime1 || "") }), + new in_window.org.pkijs.asn1.INTEGER({ name: (names.prime2 || "") }), + new in_window.org.pkijs.asn1.INTEGER({ name: (names.exponent1 || "") }), + new in_window.org.pkijs.asn1.INTEGER({ name: (names.exponent2 || "") }), + new in_window.org.pkijs.asn1.INTEGER({ name: (names.coefficient || "") }), + new in_window.org.pkijs.asn1.SEQUENCE({ + optional: true, + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.otherPrimeInfos || ""), + value: in_window.org.pkijs.schema.x509.OtherPrimeInfo(names.otherPrimeInfo || {}) + }) + ] + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "RSASSA-PSS-params" type (RFC3447) + //************************************************************************************** + in_window.org.pkijs.schema.x509.RSASSA_PSS_params = + function() + { + //RSASSA-PSS-params ::= SEQUENCE { + // hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, + // maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier, + // saltLength [2] INTEGER DEFAULT 20, + // trailerField [3] INTEGER DEFAULT 1 } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + optional: true, + value: [in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.hashAlgorithm || {})] + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + optional: true, + value: [in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.maskGenAlgorithm || {})] + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 2 // [2] + }, + optional: true, + value: [new in_window.org.pkijs.asn1.INTEGER({ name: (names.saltLength || "") })] + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 3 // [3] + }, + optional: true, + value: [new in_window.org.pkijs.asn1.INTEGER({ name: (names.trailerField || "") })] + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "SubjectPublicKeyInfo" type + //************************************************************************************** + in_window.org.pkijs.schema.PUBLIC_KEY_INFO = + function() + { + //SubjectPublicKeyInfo ::= SEQUENCE { + // algorithm AlgorithmIdentifier, + // subjectPublicKey BIT STRING } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.algorithm || {}), + new in_window.org.pkijs.asn1.BITSTRING({ name: (names.subjectPublicKey || "") }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "Attribute" type + //************************************************************************************** + in_window.org.pkijs.schema.ATTRIBUTE = + function() + { + // Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE { + // type ATTRIBUTE.&id({IOSet}), + // values SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{@type}) + //} + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.OID({ name: (names.type || "") }), + new in_window.org.pkijs.asn1.SET({ + name: (names.set_name || ""), + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.values || ""), + value: new in_window.org.pkijs.asn1.ANY() + }) + ] + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "AttributeTypeAndValue" type + //************************************************************************************** + in_window.org.pkijs.schema.ATTR_TYPE_AND_VALUE = + function() + { + //AttributeTypeAndValue ::= SEQUENCE { + // type AttributeType, + // value AttributeValue } + // + //AttributeType ::= OBJECT IDENTIFIER + // + //AttributeValue ::= ANY -- DEFINED BY AttributeType + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.OID({ name: (names.type || "") }), + new in_window.org.pkijs.asn1.ANY({ name: (names.value || "") }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "RelativeDistinguishedName" type + //************************************************************************************** + in_window.org.pkijs.schema.RDN = + function() + { + //RDNSequence ::= SEQUENCE OF RelativeDistinguishedName + // + //RelativeDistinguishedName ::= + //SET SIZE (1..MAX) OF AttributeTypeAndValue + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.repeated_sequence || ""), + value: new in_window.org.pkijs.asn1.SET({ + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.repeated_set || ""), + value: in_window.org.pkijs.schema.ATTR_TYPE_AND_VALUE(names.attr_type_and_value || {}) + }) + ] + }) + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "Extension" type + //************************************************************************************** + in_window.org.pkijs.schema.EXTENSION = + function() + { + //Extension ::= SEQUENCE { + // extnID OBJECT IDENTIFIER, + // critical BOOLEAN DEFAULT FALSE, + // extnValue OCTET STRING + //} + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.OID({ name: (names.extnID || "") }), + new in_window.org.pkijs.asn1.BOOLEAN({ + name: (names.critical || ""), + optional: true + }), + new in_window.org.pkijs.asn1.OCTETSTRING({ name: (names.extnValue || "") }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "Extensions" type (sequence of many Extension) + //************************************************************************************** + in_window.org.pkijs.schema.EXTENSIONS = + function(input_names, input_optional) + { + //Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + + var names = in_window.org.pkijs.getNames(arguments[0]); + var optional = input_optional || false; + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + optional: optional, + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.extensions || ""), + value: in_window.org.pkijs.schema.EXTENSION(names.extension || {}) + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "AuthorityKeyIdentifier" type of extension + //************************************************************************************** + in_window.org.pkijs.schema.x509.AuthorityKeyIdentifier = + function() + { + // AuthorityKeyIdentifier OID ::= 2.5.29.35 + // + //AuthorityKeyIdentifier ::= SEQUENCE { + // keyIdentifier [0] KeyIdentifier OPTIONAL, + // authorityCertIssuer [1] GeneralNames OPTIONAL, + // authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } + // + //KeyIdentifier ::= OCTET STRING + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + name: (names.keyIdentifier || ""), + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + } + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.authorityCertIssuer || ""), + value: in_window.org.pkijs.schema.GENERAL_NAME() + }) + ] + }), + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + name: (names.authorityCertSerialNumber || ""), + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 2 // [2] + } + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "PrivateKeyUsagePeriod" type of extension + //************************************************************************************** + in_window.org.pkijs.schema.x509.PrivateKeyUsagePeriod = + function() + { + // PrivateKeyUsagePeriod OID ::= 2.5.29.16 + // + //PrivateKeyUsagePeriod ::= SEQUENCE { + // notBefore [0] GeneralizedTime OPTIONAL, + // notAfter [1] GeneralizedTime OPTIONAL } + //-- either notBefore or notAfter MUST be present + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + name: (names.notBefore || ""), + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + } + }), + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + name: (names.notAfter || ""), + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + } + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "IssuerAltName" and "SubjectAltName" types of extension + //************************************************************************************** + in_window.org.pkijs.schema.x509.AltName = + function() + { + // SubjectAltName OID ::= 2.5.29.17 + // IssuerAltName OID ::= 2.5.29.18 + // + // AltName ::= GeneralNames + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.altNames || ""), + value: in_window.org.pkijs.schema.GENERAL_NAME() + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "SubjectDirectoryAttributes" type of extension + //************************************************************************************** + in_window.org.pkijs.schema.x509.SubjectDirectoryAttributes = + function() + { + // SubjectDirectoryAttributes OID ::= 2.5.29.9 + // + //SubjectDirectoryAttributes ::= SEQUENCE SIZE (1..MAX) OF Attribute + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.attributes || ""), + value: in_window.org.pkijs.schema.ATTRIBUTE() + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "GeneralSubtree" type + //************************************************************************************** + in_window.org.pkijs.schema.x509.GeneralSubtree = + function() + { + //GeneralSubtree ::= SEQUENCE { + // base GeneralName, + // minimum [0] BaseDistance DEFAULT 0, + // maximum [1] BaseDistance OPTIONAL } + // + //BaseDistance ::= INTEGER (0..MAX) + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + in_window.org.pkijs.schema.GENERAL_NAME(names.base || ""), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [new in_window.org.pkijs.asn1.INTEGER({ name: (names.minimum || "") })] + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [new in_window.org.pkijs.asn1.INTEGER({ name: (names.maximum || "") })] + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "NameConstraints" type of extension + //************************************************************************************** + in_window.org.pkijs.schema.x509.NameConstraints = + function() + { + // NameConstraints OID ::= 2.5.29.30 + // + //NameConstraints ::= SEQUENCE { + // permittedSubtrees [0] GeneralSubtrees OPTIONAL, + // excludedSubtrees [1] GeneralSubtrees OPTIONAL } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.permittedSubtrees || ""), + value: in_window.org.pkijs.schema.x509.GeneralSubtree() + }) + ] + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.excludedSubtrees || ""), + value: in_window.org.pkijs.schema.x509.GeneralSubtree() + }) + ] + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "BasicConstraints" type of extension + //************************************************************************************** + in_window.org.pkijs.schema.x509.BasicConstraints = + function() + { + // BasicConstraints OID ::= 2.5.29.19 + // + //BasicConstraints ::= SEQUENCE { + // cA BOOLEAN DEFAULT FALSE, + // pathLenConstraint INTEGER (0..MAX) OPTIONAL } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.BOOLEAN({ + optional: true, + name: (names.cA || "") + }), + new in_window.org.pkijs.asn1.INTEGER({ + optional: true, + name: (names.pathLenConstraint || "") + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "PolicyQualifierInfo" type + //************************************************************************************** + in_window.org.pkijs.schema.x509.PolicyQualifierInfo = + function() + { + //PolicyQualifierInfo ::= SEQUENCE { + // policyQualifierId PolicyQualifierId, + // qualifier ANY DEFINED BY policyQualifierId } + // + //id-qt OBJECT IDENTIFIER ::= { id-pkix 2 } + //id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 } + //id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 } + // + //PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice ) + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.OID({ name: (names.policyQualifierId || "") }), + new in_window.org.pkijs.asn1.ANY({ name: (names.qualifier || "") }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "PolicyInformation" type + //************************************************************************************** + in_window.org.pkijs.schema.x509.PolicyInformation = + function() + { + //PolicyInformation ::= SEQUENCE { + // policyIdentifier CertPolicyId, + // policyQualifiers SEQUENCE SIZE (1..MAX) OF + // PolicyQualifierInfo OPTIONAL } + // + //CertPolicyId ::= OBJECT IDENTIFIER + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.OID({ name: (names.policyIdentifier || "") }), + new in_window.org.pkijs.asn1.SEQUENCE({ + optional: true, + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.policyQualifiers || ""), + value: in_window.org.pkijs.schema.x509.PolicyQualifierInfo() + }) + ] + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "CertificatePolicies" type of extension + //************************************************************************************** + in_window.org.pkijs.schema.x509.CertificatePolicies = + function() + { + // CertificatePolicies OID ::= 2.5.29.32 + // + //certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.certificatePolicies || ""), + value: in_window.org.pkijs.schema.x509.PolicyInformation() + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "PolicyMapping" type + //************************************************************************************** + in_window.org.pkijs.schema.x509.PolicyMapping = + function() + { + //PolicyMapping ::= SEQUENCE { + // issuerDomainPolicy CertPolicyId, + // subjectDomainPolicy CertPolicyId } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.OID({ name: (names.issuerDomainPolicy || "") }), + new in_window.org.pkijs.asn1.OID({ name: (names.subjectDomainPolicy || "") }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "PolicyMappings" type of extension + //************************************************************************************** + in_window.org.pkijs.schema.x509.PolicyMappings = + function() + { + // PolicyMappings OID ::= 2.5.29.33 + // + //PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF PolicyMapping + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.mappings || ""), + value: in_window.org.pkijs.schema.x509.PolicyMapping() + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "PolicyConstraints" type of extension + //************************************************************************************** + in_window.org.pkijs.schema.x509.PolicyConstraints = + function() + { + // PolicyMappings OID ::= 2.5.29.36 + // + //PolicyConstraints ::= SEQUENCE { + // requireExplicitPolicy [0] SkipCerts OPTIONAL, + // inhibitPolicyMapping [1] SkipCerts OPTIONAL } + // + //SkipCerts ::= INTEGER (0..MAX) + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + name: (names.requireExplicitPolicy || ""), + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + } + }), // IMPLICIT integer value + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + name: (names.inhibitPolicyMapping || ""), + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + } + }) // IMPLICIT integer value + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "ExtKeyUsage" type of extension + //************************************************************************************** + in_window.org.pkijs.schema.x509.ExtKeyUsage = + function() + { + // ExtKeyUsage OID ::= 2.5.29.37 + // + // ExtKeyUsage ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId + + // KeyPurposeId ::= OBJECT IDENTIFIER + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.keyPurposes || ""), + value: new in_window.org.pkijs.asn1.OID() + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "DistributionPoint" type + //************************************************************************************** + in_window.org.pkijs.schema.x509.DistributionPoint = + function() + { + //DistributionPoint ::= SEQUENCE { + // distributionPoint [0] DistributionPointName OPTIONAL, + // reasons [1] ReasonFlags OPTIONAL, + // cRLIssuer [2] GeneralNames OPTIONAL } + // + //DistributionPointName ::= CHOICE { + // fullName [0] GeneralNames, + // nameRelativeToCRLIssuer [1] RelativeDistinguishedName } + // + //ReasonFlags ::= BIT STRING { + // unused (0), + // keyCompromise (1), + // cACompromise (2), + // affiliationChanged (3), + // superseded (4), + // cessationOfOperation (5), + // certificateHold (6), + // privilegeWithdrawn (7), + // aACompromise (8) } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [ + new in_window.org.pkijs.asn1.CHOICE({ + value: [ + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + name: (names.distributionPoint || ""), + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.distributionPoint_names || ""), + value: in_window.org.pkijs.schema.GENERAL_NAME() + }) + ] + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + name: (names.distributionPoint || ""), + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: in_window.org.pkijs.schema.RDN().value_block.value + }) + ] + }) + ] + }), + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + name: (names.reasons || ""), + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + } + }), // IMPLICIT bitstring value + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + name: (names.cRLIssuer || ""), + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 2 // [2] + }, + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.cRLIssuer_names || ""), + value: in_window.org.pkijs.schema.GENERAL_NAME() + }) + ] + }) // IMPLICIT bitstring value + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "CRLDistributionPoints" type of extension + //************************************************************************************** + in_window.org.pkijs.schema.x509.CRLDistributionPoints = + function() + { + // CRLDistributionPoints OID ::= 2.5.29.31 + // + //CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.distributionPoints || ""), + value: in_window.org.pkijs.schema.x509.DistributionPoint() + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "AccessDescription" type + //************************************************************************************** + in_window.org.pkijs.schema.x509.AccessDescription = + function() + { + //AccessDescription ::= SEQUENCE { + // accessMethod OBJECT IDENTIFIER, + // accessLocation GeneralName } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.OID({ name: (names.accessMethod || "") }), + in_window.org.pkijs.schema.GENERAL_NAME(names.accessLocation || "") + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "AuthorityInfoAccess" and "SubjectInfoAccess" types of extension + //************************************************************************************** + in_window.org.pkijs.schema.x509.InfoAccess = + function() + { + // AuthorityInfoAccess OID ::= 1.3.6.1.5.5.7.1.1 + // SubjectInfoAccess OID ::= 1.3.6.1.5.5.7.1.11 + // + //AuthorityInfoAccessSyntax ::= + //SEQUENCE SIZE (1..MAX) OF AccessDescription + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.accessDescriptions || ""), + value: in_window.org.pkijs.schema.x509.AccessDescription() + }) + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region ASN.1 schema definition for "IssuingDistributionPoint" type of extension + //************************************************************************************** + in_window.org.pkijs.schema.x509.IssuingDistributionPoint = + function() + { + // IssuingDistributionPoint OID ::= 2.5.29.28 + // + //IssuingDistributionPoint ::= SEQUENCE { + // distributionPoint [0] DistributionPointName OPTIONAL, + // onlyContainsUserCerts [1] BOOLEAN DEFAULT FALSE, + // onlyContainsCACerts [2] BOOLEAN DEFAULT FALSE, + // onlySomeReasons [3] ReasonFlags OPTIONAL, + // indirectCRL [4] BOOLEAN DEFAULT FALSE, + // onlyContainsAttributeCerts [5] BOOLEAN DEFAULT FALSE } + // + //ReasonFlags ::= BIT STRING { + // unused (0), + // keyCompromise (1), + // cACompromise (2), + // affiliationChanged (3), + // superseded (4), + // cessationOfOperation (5), + // certificateHold (6), + // privilegeWithdrawn (7), + // aACompromise (8) } + + var names = in_window.org.pkijs.getNames(arguments[0]); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + name: (names.block_name || ""), + value: [ + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [ + new in_window.org.pkijs.asn1.CHOICE({ + value: [ + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + name: (names.distributionPoint || ""), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: (names.distributionPoint_names || ""), + value: in_window.org.pkijs.schema.GENERAL_NAME() + }) + ] + }), + new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + name: (names.distributionPoint || ""), + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: in_window.org.pkijs.schema.RDN().value_block.value + }) + ] + }) + ] + }), + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + name: (names.onlyContainsUserCerts || ""), + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + } + }), // IMPLICIT boolean value + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + name: (names.onlyContainsCACerts || ""), + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 2 // [2] + } + }), // IMPLICIT boolean value + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + name: (names.onlySomeReasons || ""), + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 3 // [3] + } + }), // IMPLICIT bitstring value + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + name: (names.indirectCRL || ""), + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 4 // [4] + } + }), // IMPLICIT boolean value + new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + name: (names.onlyContainsAttributeCerts || ""), + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 5 // [5] + } + }) // IMPLICIT boolean value + ] + })); + }; + //************************************************************************************** + // #endregion + //************************************************************************************** +} +)(typeof exports !== "undefined" ? exports : window); \ No newline at end of file diff --git a/express-server/node_modules/pkijs/org/pkijs/x509_simpl.js b/express-server/node_modules/pkijs/org/pkijs/x509_simpl.js new file mode 100644 index 00000000..5012d391 --- /dev/null +++ b/express-server/node_modules/pkijs/org/pkijs/x509_simpl.js @@ -0,0 +1,7301 @@ +/* + * Copyright (c) 2014, GMO GlobalSign + * Copyright (c) 2015-2016, Peculiar Ventures + * All rights reserved. + * + * Author 2014-2016, Yury Strozhevsky . + * + * 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 copyright holder 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. + * + */ +( +function(in_window) +{ + //************************************************************************************** + // #region Declaration of global variables + //************************************************************************************** + // #region "org" namespace + if(typeof in_window.org === "undefined") + in_window.org = {}; + else + { + if(typeof in_window.org !== "object") + throw new Error("Name org already exists and it's not an object"); + } + // #endregion + + // #region "org.pkijs" namespace + if(typeof in_window.org.pkijs === "undefined") + in_window.org.pkijs = {}; + else + { + if(typeof in_window.org.pkijs !== "object") + throw new Error("Name org.pkijs already exists and it's not an object" + " but " + (typeof in_window.org.pkijs)); + } + // #endregion + + // #region "org.pkijs.simpl" namespace + if(typeof in_window.org.pkijs.simpl === "undefined") + in_window.org.pkijs.simpl = {}; + else + { + if(typeof in_window.org.pkijs.simpl !== "object") + throw new Error("Name org.pkijs.simpl already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.simpl)); + } + // #endregion + + // #region "org.pkijs.simpl.x509" namespace + if(typeof in_window.org.pkijs.simpl.x509 === "undefined") + in_window.org.pkijs.simpl.x509 = {}; + else + { + if(typeof in_window.org.pkijs.simpl.x509 !== "object") + throw new Error("Name org.pkijs.simpl.x509 already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.simpl.x509)); + } + // #endregion + + // #region "local" namespace + var local = {}; + // #endregion + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "Time" type + //************************************************************************************** + in_window.org.pkijs.simpl.TIME = + function() + { + // #region Internal properties of the object + this.type = 0; // 0 - UTCTime; 1 - GeneralizedTime; 2 - empty value + this.value = new Date(0, 0, 0); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.TIME.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.type = (arguments[0].type || 0); + this.value = (arguments[0].value || (new Date(0, 0, 0))); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.TIME.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.TIME({ + names: { + utcTimeName: "utcTimeName", + generalTimeName: "generalTimeName" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for TIME"); + // #endregion + + // #region Get internal properties from parsed schema + if("utcTimeName" in asn1.result) + { + this.type = 0; + this.value = asn1.result.utcTimeName.toDate(); + } + if("generalTimeName" in asn1.result) + { + this.type = 1; + this.value = asn1.result.generalTimeName.toDate(); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.TIME.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + var result = {}; + + if(this.type === 0) + result = new in_window.org.pkijs.asn1.UTCTIME({ value_date: this.value }); + if(this.type === 1) + result = new in_window.org.pkijs.asn1.GENERALIZEDTIME({ value_date: this.value }); + + return result; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.TIME.prototype.toJSON = + function() + { + return { + type: this.type, + value: this.value + }; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "GeneralName" type + //************************************************************************************** + in_window.org.pkijs.simpl.GENERAL_NAME = + function() + { + // #region Internal properties of the object + this.NameType = 9; // Name type - from a tagged value (0 for "otherName", 1 for "rfc822Name" etc.) + this.Name = {}; + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.GENERAL_NAME.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.NameType = arguments[0].NameType || 9; + if("Name" in arguments[0]) + this.Name = arguments[0].Name; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.GENERAL_NAME.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.GENERAL_NAME({ + names: { + block_name: "block_name", + otherName: "otherName", + rfc822Name: "rfc822Name", + dNSName: "dNSName", + x400Address: "x400Address", + directoryName: { + names: { + block_name: "directoryName" + } + }, + ediPartyName: "ediPartyName", + uniformResourceIdentifier: "uniformResourceIdentifier", + iPAddress: "iPAddress", + registeredID: "registeredID" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for GENERAL_NAME"); + // #endregion + + // #region Get internal properties from parsed schema + this.NameType = asn1.result["block_name"].id_block.tag_number; + + switch(this.NameType) + { + case 0: // otherName + this.Name = asn1.result["block_name"]; + break; + case 1: // rfc822Name + dNSName + uniformResourceIdentifier + case 2: + case 6: + { + var value = asn1.result["block_name"]; + + value.id_block.tag_class = 1; // UNIVERSAL + value.id_block.tag_number = 22; // IA5STRING + + var value_ber = value.toBER(false); + + this.Name = in_window.org.pkijs.fromBER(value_ber).result.value_block.value; + } + break; + case 3: // x400Address + this.Name = asn1.result["block_name"]; + break; + case 4: // directoryName + this.Name = new in_window.org.pkijs.simpl.RDN({ schema: asn1.result["directoryName"] }); + break; + case 5: // ediPartyName + this.Name = asn1.result["ediPartyName"]; + break; + case 7: // iPAddress + this.Name = new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: asn1.result["block_name"].value_block.value_hex }); + break; + case 8: // registeredID + { + var value = asn1.result["block_name"]; + + value.id_block.tag_class = 1; // UNIVERSAL + value.id_block.tag_number = 6; // OID + + var value_ber = value.toBER(false); + + this.Name = in_window.org.pkijs.fromBER(value_ber).result.value_block.toString(); // Getting a string representation of the OID + } + break; + default:; + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.GENERAL_NAME.prototype.toSchema = + function(schema) + { + // #region Construct and return new ASN.1 schema for this object + switch(this.NameType) + { + case 0: + case 3: + case 5: + return new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: this.NameType + }, + value: [ + this.Name + ] + }); + + break; + case 1: + case 2: + case 6: + { + var value = new in_window.org.pkijs.asn1.IA5STRING({ value: this.Name }); + + value.id_block.tag_class = 3; + value.id_block.tag_number = this.NameType; + + return value; + } + break; + case 4: + return new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 4 + }, + value: [this.Name.toSchema()] + }); + break; + case 7: + { + var value = this.Name; + + value.id_block.tag_class = 3; + value.id_block.tag_number = this.NameType; + + return value; + } + break; + case 8: + { + var value = new in_window.org.pkijs.asn1.OID({ value: this.Name }); + + value.id_block.tag_class = 3; + value.id_block.tag_number = this.NameType; + + return value; + } + break; + default: + return in_window.org.pkijs.schema.GENERAL_NAME(); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.GENERAL_NAME.prototype.toJSON = + function() + { + var _object = { + NameType: this.NameType + }; + + if((typeof this.Name) === "string") + _object.Name = this.Name; + else + _object.Name = this.Name.toJSON(); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "GeneralNames" type + //************************************************************************************** + in_window.org.pkijs.simpl.GENERAL_NAMES = + function() + { + // #region Internal properties of the object + this.names = new Array(); // Array of "org.pkijs.simpl.GENERAL_NAME" + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.GENERAL_NAMES.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.names = arguments[0].names || new Array(); // Array of "org.pkijs.simpl.GENERAL_NAME" + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.GENERAL_NAMES.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + new in_window.org.pkijs.asn1.REPEATED({ + name: "names", + value: in_window.org.pkijs.schema.GENERAL_NAME() + }) + ] + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for GENERAL_NAMES"); + // #endregion + + // #region Get internal properties from parsed schema + var n = asn1.result["names"]; + + for(var i = 0; i < n.length; i++) + this.names.push(new in_window.org.pkijs.simpl.GENERAL_NAME({ schema: n[i] })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.GENERAL_NAMES.prototype.toSchema = + function(schema) + { + // #region Construct and return new ASN.1 schema for this object + var output_array = new Array(); + + for(var i = 0; i < this.names.length; i++) + output_array.push(this.names[i].toSchema()); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.GENERAL_NAMES.prototype.toJSON = + function() + { + var _names = new Array(); + + for(var i = 0; i < this.names.length; i++) + _names.push(this.names[i].toJSON()); + + return { + names: _names + }; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "AlgorithmIdentifier" type + //************************************************************************************** + in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER = + function() + { + // #region Internal properties of the object + this.algorithm_id = ""; + // OPTIONAL this.algorithm_params = new in_window.org.pkijs.asn1.NULL(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.algorithm_id = arguments[0].algorithm_id || ""; + if("algorithm_params" in arguments[0]) + this.algorithm_params = arguments[0].algorithm_params; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER({ + names: { + algorithmIdentifier: "algorithm", + algorithmParams: "params" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for ALGORITHM_IDENTIFIER"); + // #endregion + + // #region Get internal properties from parsed schema + this.algorithm_id = asn1.result.algorithm.value_block.toString(); + if("params" in asn1.result) + this.algorithm_params = asn1.result.params; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + output_array.push(new in_window.org.pkijs.asn1.OID({ value: this.algorithm_id })); + if("algorithm_params" in this) + output_array.push(this.algorithm_params); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER.prototype.toJSON = + function() + { + var _object = { + algorithm_id: this.algorithm_id + }; + + if("algorithm_params" in this) + _object.algorithm_params = this.algorithm_params.toJSON(); + + return _object; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER.prototype.isEqual = + function(algorithmIdentifier) + { + /// Check that two "ALGORITHM_IDENTIFIERs" are equal + /// The algorithm identifier to compare with + + // #region Check input type + if((algorithmIdentifier instanceof in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER) == false) + return false; + // #endregion + + // #region Check "algorithm_id" + if(this.algorithm_id != algorithmIdentifier.algorithm_id) + return false; + // #endregion + + // #region Check "algorithm_params" + if("algorithm_params" in this) + { + if("algorithm_params" in algorithmIdentifier) + { + return JSON.stringify(this.algorithm_params) == JSON.stringify(algorithmIdentifier.algorithm_params); + } + else + return false; + } + else + { + if("algorithm_params" in algorithmIdentifier) + return false; + } + // #endregion + + return true; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "RSAPublicKey" type (RFC3447) + //************************************************************************************** + in_window.org.pkijs.simpl.x509.RSAPublicKey = + function() + { + // #region Internal properties of the object + this.modulus = new in_window.org.pkijs.asn1.INTEGER(); + this.publicExponent = new in_window.org.pkijs.asn1.INTEGER(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.x509.RSAPublicKey.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.modulus = arguments[0].modulus || new in_window.org.pkijs.asn1.INTEGER(); + this.publicExponent = arguments[0].publicExponent || new in_window.org.pkijs.asn1.INTEGER(); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.RSAPublicKey.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.x509.RSAPublicKey({ + names: { + modulus: "modulus", + publicExponent: "publicExponent" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for RSAPublicKey"); + // #endregion + + // #region Get internal properties from parsed schema + this.modulus = asn1.result["modulus"]; + this.publicExponent = asn1.result["publicExponent"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.RSAPublicKey.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + this.modulus, + this.publicExponent + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.RSAPublicKey.prototype.toJSON = + function() + { + return { + modulus: this.modulus.toJSON(), + publicExponent: this.publicExponent.toJSON() + }; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "OtherPrimeInfo" type (RFC3447) + //************************************************************************************** + in_window.org.pkijs.simpl.x509.OtherPrimeInfo = + function() + { + // #region Internal properties of the object + this.prime = new in_window.org.pkijs.asn1.INTEGER(); + this.exponent = new in_window.org.pkijs.asn1.INTEGER(); + this.coefficient = new in_window.org.pkijs.asn1.INTEGER(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.x509.OtherPrimeInfo.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.prime = arguments[0].prime || new in_window.org.pkijs.asn1.INTEGER(); + this.exponent = arguments[0].exponent || new in_window.org.pkijs.asn1.INTEGER(); + this.coefficient = arguments[0].coefficient || new in_window.org.pkijs.asn1.INTEGER(); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.OtherPrimeInfo.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.x509.OtherPrimeInfo({ + names: { + prime: "prime", + exponent: "exponent", + coefficient: "coefficient" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for OtherPrimeInfo"); + // #endregion + + // #region Get internal properties from parsed schema + this.prime = asn1.result["prime"]; + this.exponent = asn1.result["exponent"]; + this.coefficient = asn1.result["coefficient"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.OtherPrimeInfo.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + this.prime, + this.exponent, + this.coefficient + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.OtherPrimeInfo.prototype.toJSON = + function() + { + return { + prime: this.prime.toJSON(), + exponent: this.exponent.toJSON(), + coefficient: this.coefficient.toJSON() + }; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "RSAPrivateKey" type (RFC3447) + //************************************************************************************** + in_window.org.pkijs.simpl.x509.RSAPrivateKey = + function() + { + // #region Internal properties of the object + this.version = 0; + this.modulus = new in_window.org.pkijs.asn1.INTEGER(); + this.publicExponent = new in_window.org.pkijs.asn1.INTEGER(); + this.privateExponent = new in_window.org.pkijs.asn1.INTEGER(); + this.prime1 = new in_window.org.pkijs.asn1.INTEGER(); + this.prime2 = new in_window.org.pkijs.asn1.INTEGER(); + this.exponent1 = new in_window.org.pkijs.asn1.INTEGER(); + this.exponent2 = new in_window.org.pkijs.asn1.INTEGER(); + this.coefficient = new in_window.org.pkijs.asn1.INTEGER(); + // OPTIONAL this.otherPrimeInfos = new Array(); // Array of "OtherPrimeInfo" + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.x509.RSAPrivateKey.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.version = arguments[0].version || 0; + this.modulus = arguments[0].modulus || new in_window.org.pkijs.asn1.INTEGER(); + this.publicExponent = arguments[0].publicExponent || new in_window.org.pkijs.asn1.INTEGER(); + this.privateExponent = arguments[0].privateExponent || new in_window.org.pkijs.asn1.INTEGER(); + this.prime1 = arguments[0].prime1 || new in_window.org.pkijs.asn1.INTEGER(); + this.prime2 = arguments[0].prime2 || new in_window.org.pkijs.asn1.INTEGER(); + this.exponent1 = arguments[0].exponent1 || new in_window.org.pkijs.asn1.INTEGER(); + this.exponent2 = arguments[0].exponent2 || new in_window.org.pkijs.asn1.INTEGER(); + this.coefficient = arguments[0].coefficient || new in_window.org.pkijs.asn1.INTEGER(); + if("otherPrimeInfos" in arguments[0]) + this.otherPrimeInfos = arguments[0].otherPrimeInfos || new Array(); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.RSAPrivateKey.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.x509.RSAPrivateKey({ + names: { + version: "version", + modulus: "modulus", + publicExponent: "publicExponent", + privateExponent: "privateExponent", + prime1: "prime1", + prime2: "prime2", + exponent1: "exponent1", + exponent2: "exponent2", + coefficient: "coefficient", + otherPrimeInfos: "otherPrimeInfos" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for RSAPrivateKey"); + // #endregion + + // #region Get internal properties from parsed schema + this.version = asn1.result["version"].value_block.value_dec; + this.modulus = asn1.result["modulus"]; + this.publicExponent = asn1.result["publicExponent"]; + this.privateExponent = asn1.result["privateExponent"]; + this.prime1 = asn1.result["prime1"]; + this.prime2 = asn1.result["prime2"]; + this.exponent1 = asn1.result["exponent1"]; + this.exponent2 = asn1.result["exponent2"]; + this.coefficient = asn1.result["coefficient"]; + + if("otherPrimeInfos" in asn1.result) + { + var otherPrimeInfos_array = asn1.result["otherPrimeInfos"]; + + for(var i = 0; i < otherPrimeInfos_array.length; i++) + this.otherPrimeInfos.push(new in_window.org.pkijs.simpl.x509.OtherPrimeInfo({ schema: otherPrimeInfos_array[i] })); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.RSAPrivateKey.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + output_array.push(new in_window.org.pkijs.asn1.INTEGER({ value: this.version })); + output_array.push(this.modulus); + output_array.push(this.publicExponent); + output_array.push(this.privateExponent); + output_array.push(this.prime1); + output_array.push(this.prime2); + output_array.push(this.exponent1); + output_array.push(this.exponent2); + output_array.push(this.coefficient); + + if("otherPrimeInfos" in this) + { + var otherPrimeInfos_array = new Array(); + + for(var i = 0; i < this.otherPrimeInfos.length; i++) + otherPrimeInfos_array.push(this.otherPrimeInfos[i].toSchema()); + + output_array.push(new in_window.org.pkijs.asn1.SEQUENCE({ value: otherPrimeInfos_array })); + } + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.RSAPrivateKey.prototype.toJSON = + function() + { + var _object = { + version: this.version, + modulus: this.modulus.toJSON(), + publicExponent: this.publicExponent.toJSON(), + privateExponent: this.privateExponent.toJSON(), + prime1: this.prime1.toJSON(), + prime2: this.prime2.toJSON(), + exponent1: this.exponent1.toJSON(), + exponent2: this.exponent2.toJSON(), + coefficient: this.coefficient.toJSON() + }; + + if("otherPrimeInfos" in this) + { + _object.otherPrimeInfos = new Array(); + + for(var i = 0; i < this.otherPrimeInfos.length; i++) + _object.otherPrimeInfos.push(this.otherPrimeInfos[i].toJSON()); + } + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "RSASSA_PSS_params" type (RFC3447) + //************************************************************************************** + in_window.org.pkijs.simpl.x509.RSASSA_PSS_params = + function() + { + // #region Internal properties of the object + // OPTIONAL this.hashAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + // OPTIONAL this.maskGenAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + // OPTIONAL this.saltLength = 20; + // OPTIONAL this.trailerField = 1; + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.x509.RSASSA_PSS_params.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + if("hashAlgorithm" in arguments[0]) + this.hashAlgorithm = arguments[0].hashAlgorithm; + + if("maskGenAlgorithm" in arguments[0]) + this.maskGenAlgorithm = arguments[0].maskGenAlgorithm; + + if("saltLength" in arguments[0]) + this.saltLength = arguments[0].saltLength; + + if("trailerField" in arguments[0]) + this.trailerField = arguments[0].trailerField; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.RSASSA_PSS_params.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.x509.RSASSA_PSS_params({ + names: { + hashAlgorithm: { + names: { + block_name: "hashAlgorithm" + } + }, + maskGenAlgorithm: { + names: { + block_name: "maskGenAlgorithm" + } + }, + saltLength: "saltLength", + trailerField: "trailerField" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for RSASSA_PSS_params"); + // #endregion + + // #region Get internal properties from parsed schema + if("hashAlgorithm" in asn1.result) + this.hashAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["hashAlgorithm"] }); + + if("maskGenAlgorithm" in asn1.result) + this.maskGenAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["maskGenAlgorithm"] }); + + if("saltLength" in asn1.result) + this.saltLength = asn1.result["saltLength"].value_block.value_dec; + + if("trailerField" in asn1.result) + this.trailerField = asn1.result["trailerField"].value_block.value_dec; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.RSASSA_PSS_params.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + if("hashAlgorithm" in this) + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [this.hashAlgorithm.toSchema()] + })); + + if("maskGenAlgorithm" in this) + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [this.maskGenAlgorithm.toSchema()] + })); + + if("saltLength" in this) + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 2 // [2] + }, + value: [new in_window.org.pkijs.asn1.INTEGER({ value: this.saltLength })] + })); + + if("trailerField" in this) + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 3 // [3] + }, + value: [new in_window.org.pkijs.asn1.INTEGER({ value: this.trailerField })] + })); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.RSASSA_PSS_params.prototype.toJSON = + function() + { + var _object = {}; + + if("hashAlgorithm" in this) + _object.hashAlgorithm = this.hashAlgorithm.toJSON(); + + if("maskGenAlgorithm" in this) + _object.maskGenAlgorithm = this.maskGenAlgorithm.toJSON(); + + if("saltLength" in this) + _object.saltLength = this.saltLength; + + if("trailerField" in this) + _object.trailerField = this.trailerField; + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "SubjectPublicKeyInfo" type + //************************************************************************************** + in_window.org.pkijs.simpl.PUBLIC_KEY_INFO = + function() + { + // #region Internal properties of the object + this.algorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.subjectPublicKey = new in_window.org.pkijs.asn1.BITSTRING(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.PUBLIC_KEY_INFO.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.algorithm = (arguments[0].algorithm || (new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER())); + this.subjectPublicKey = (arguments[0].subjectPublicKey || (new in_window.org.pkijs.asn1.BITSTRING())); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.PUBLIC_KEY_INFO.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.PUBLIC_KEY_INFO({ + names: { + algorithm: { + names: { + block_name: "algorithm" + } + }, + subjectPublicKey: "subjectPublicKey" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for PUBLIC_KEY_INFO"); + // #endregion + + // #region Get internal properties from parsed schema + this.algorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result.algorithm }); + this.subjectPublicKey = asn1.result.subjectPublicKey; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.PUBLIC_KEY_INFO.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + this.algorithm.toSchema(), + this.subjectPublicKey + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.PUBLIC_KEY_INFO.prototype.importKey = + function(publicKey) + { + /// Public key to work with + + // #region Initial variables + var sequence = Promise.resolve(); + var _this = this; + // #endregion + + // #region Initial check + if(typeof publicKey === "undefined") + return Promise.reject("Need to provide publicKey input parameter"); + // #endregion + + // #region Get a "crypto" extension + var crypto = in_window.org.pkijs.getCrypto(); + if(typeof crypto == "undefined") + return Promise.reject("Unable to create WebCrypto object"); + // #endregion + + // #region Export public key + sequence = sequence.then( + function() + { + return crypto.exportKey("spki", publicKey); + } + ); + // #endregion + + // #region Initialize internal variables by parsing exported value + sequence = sequence.then( + function(exportedKey) + { + var asn1 = in_window.org.pkijs.fromBER(exportedKey); + try + { + in_window.org.pkijs.simpl.PUBLIC_KEY_INFO.prototype.fromSchema.call(_this, asn1.result); + } + catch(exception) + { + return Promise.reject("Error during initializing object from schema"); + } + }, + function(error) + { + return Promise.reject("Error during exporting public key: " + error); + } + ); + // #endregion + + return sequence; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.PUBLIC_KEY_INFO.prototype.toJSON = + function() + { + return { + algorithm: this.algorithm.toJSON(), + subjectPublicKey: this.subjectPublicKey.toJSON() + }; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "AttributeTypeAndValue" type (part of RelativeDistinguishedName) + //************************************************************************************** + in_window.org.pkijs.simpl.ATTR_TYPE_AND_VALUE = + function() + { + // #region Internal properties of the object + this.type = ""; + this.value = {}; // ANY -- DEFINED BY AttributeType + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.ATTR_TYPE_AND_VALUE.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.type = (arguments[0].type || ""); + this.value = (arguments[0].value || {}); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ATTR_TYPE_AND_VALUE.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.ATTR_TYPE_AND_VALUE({ + names: { + type: "type", + value: "typeValue" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for ATTR_TYPE_AND_VALUE"); + // #endregion + + // #region Get internal properties from parsed schema + this.type = asn1.result.type.value_block.toString(); + this.value = asn1.result.typeValue; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ATTR_TYPE_AND_VALUE.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + new in_window.org.pkijs.asn1.OID({ value: this.type }), + this.value + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ATTR_TYPE_AND_VALUE.prototype.isEqual = + function() + { + if(arguments[0] instanceof in_window.org.pkijs.simpl.ATTR_TYPE_AND_VALUE) + { + if(this.type !== arguments[0].type) + return false; + + if(((this.value instanceof in_window.org.pkijs.asn1.UTF8STRING) && (arguments[0].value instanceof in_window.org.pkijs.asn1.UTF8STRING)) || + ((this.value instanceof in_window.org.pkijs.asn1.BMPSTRING) && (arguments[0].value instanceof in_window.org.pkijs.asn1.BMPSTRING)) || + ((this.value instanceof in_window.org.pkijs.asn1.UNIVERSALSTRING) && (arguments[0].value instanceof in_window.org.pkijs.asn1.UNIVERSALSTRING)) || + ((this.value instanceof in_window.org.pkijs.asn1.NUMERICSTRING) && (arguments[0].value instanceof in_window.org.pkijs.asn1.NUMERICSTRING)) || + ((this.value instanceof in_window.org.pkijs.asn1.PRINTABLESTRING) && (arguments[0].value instanceof in_window.org.pkijs.asn1.PRINTABLESTRING)) || + ((this.value instanceof in_window.org.pkijs.asn1.TELETEXSTRING) && (arguments[0].value instanceof in_window.org.pkijs.asn1.TELETEXSTRING)) || + ((this.value instanceof in_window.org.pkijs.asn1.VIDEOTEXSTRING) && (arguments[0].value instanceof in_window.org.pkijs.asn1.VIDEOTEXSTRING)) || + ((this.value instanceof in_window.org.pkijs.asn1.IA5STRING) && (arguments[0].value instanceof in_window.org.pkijs.asn1.IA5STRING)) || + ((this.value instanceof in_window.org.pkijs.asn1.GRAPHICSTRING) && (arguments[0].value instanceof in_window.org.pkijs.asn1.GRAPHICSTRING)) || + ((this.value instanceof in_window.org.pkijs.asn1.VISIBLESTRING) && (arguments[0].value instanceof in_window.org.pkijs.asn1.VISIBLESTRING)) || + ((this.value instanceof in_window.org.pkijs.asn1.GENERALSTRING) && (arguments[0].value instanceof in_window.org.pkijs.asn1.GENERALSTRING)) || + ((this.value instanceof in_window.org.pkijs.asn1.CHARACTERSTRING) && (arguments[0].value instanceof in_window.org.pkijs.asn1.CHARACTERSTRING))) + { + var value1 = in_window.org.pkijs.stringPrep(this.value.value_block.value); + var value2 = in_window.org.pkijs.stringPrep(arguments[0].value.value_block.value); + + if(value1.localeCompare(value2) !== 0) + return false; + } + else // Comparing as two ArrayBuffers + { + if(in_window.org.pkijs.isEqual_buffer(this.value.value_before_decode, arguments[0].value.value_before_decode) === false) + return false; + } + + return true; + } + else + return false; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ATTR_TYPE_AND_VALUE.prototype.toJSON = + function() + { + var _object = { + type: this.type + }; + + if(Object.keys(this.value).length !== 0) + _object.value = this.value.toJSON(); + else + _object.value = this.value; + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "RelativeDistinguishedName" type + //************************************************************************************** + in_window.org.pkijs.simpl.RDN = + function() + { + // #region Internal properties of the object + /// Array of "type and value" objects + this.types_and_values = new Array(); + /// Value of the RDN before decoding from schema + this.value_before_decode = new ArrayBuffer(0); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.RDN.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.types_and_values = (arguments[0].types_and_values || (new Array())); + this.value_before_decode = arguments[0].value_before_decode || new ArrayBuffer(0); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.RDN.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.RDN({ + names: { + block_name: "RDN", + repeated_set: "types_and_values" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for RDN"); + // #endregion + + // #region Get internal properties from parsed schema + if("types_and_values" in asn1.result) // Could be a case when there is no "types and values" + { + var types_and_values_array = asn1.result.types_and_values; + for(var i = 0; i < types_and_values_array.length; i++) + this.types_and_values.push(new in_window.org.pkijs.simpl.ATTR_TYPE_AND_VALUE({ schema: types_and_values_array[i] })); + } + + this.value_before_decode = asn1.result.RDN.value_before_decode; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.RDN.prototype.toSchema = + function() + { + // #region Decode stored TBS value + if(this.value_before_decode.byteLength === 0) // No stored encoded array, create "from scratch" + { + // #region Create array for output set + var output_array = new Array(); + + for(var i = 0; i < this.types_and_values.length; i++) + output_array.push(this.types_and_values[i].toSchema()); + // #endregion + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [new in_window.org.pkijs.asn1.SET({ value: output_array })] + })); + } + + var asn1 = in_window.org.pkijs.fromBER(this.value_before_decode); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return asn1.result; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.RDN.prototype.isEqual = + function() + { + if(arguments[0] instanceof in_window.org.pkijs.simpl.RDN) + { + if(this.types_and_values.length != arguments[0].types_and_values.length) + return false; + + for(var i = 0; i < this.types_and_values.length; i++) + { + if(this.types_and_values[i].isEqual(arguments[0].types_and_values[i]) === false) + return false; + } + + return true; + } + else + { + if(arguments[0] instanceof ArrayBuffer) + return in_window.org.pkijs.isEqual_buffer(this.value_before_decode, arguments[0]); + else + return false; + } + + return false; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.RDN.prototype.toJSON = + function() + { + var _object = { + types_and_values: new Array() + }; + + for(var i = 0; i < this.types_and_values.length; i++) + _object.types_and_values.push(this.types_and_values[i].toJSON()); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "AuthorityKeyIdentifier" type of extension + //************************************************************************************** + in_window.org.pkijs.simpl.x509.AuthorityKeyIdentifier = + function() + { + // #region Internal properties of the object + // OPTIONAL this.keyIdentifier - OCTETSTRING + // OPTIONAL this.authorityCertIssuer - Array of GeneralName + // OPTIONAL this.authorityCertSerialNumber - INTEGER + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.x509.AuthorityKeyIdentifier.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + if("keyIdentifier" in arguments[0]) + this.keyIdentifier = arguments[0].keyIdentifier; + + if("authorityCertIssuer" in arguments[0]) + this.authorityCertIssuer = arguments[0].authorityCertIssuer; + + if("authorityCertSerialNumber" in arguments[0]) + this.authorityCertSerialNumber = arguments[0].authorityCertSerialNumber; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.AuthorityKeyIdentifier.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.x509.AuthorityKeyIdentifier({ + names: { + keyIdentifier: "keyIdentifier", + authorityCertIssuer: "authorityCertIssuer", + authorityCertSerialNumber: "authorityCertSerialNumber" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for AuthorityKeyIdentifier"); + // #endregion + + // #region Get internal properties from parsed schema + if("keyIdentifier" in asn1.result) + { + asn1.result["keyIdentifier"].id_block.tag_class = 1; // UNIVERSAL + asn1.result["keyIdentifier"].id_block.tag_number = 4; // OCTETSTRING + + this.keyIdentifier = asn1.result["keyIdentifier"]; + } + + if("authorityCertIssuer" in asn1.result) + { + this.authorityCertIssuer = new Array(); + var issuer_array = asn1.result["authorityCertIssuer"]; + + for(var i = 0; i < issuer_array.length; i++) + this.authorityCertIssuer.push(new in_window.org.pkijs.simpl.GENERAL_NAME({ schema: issuer_array[i] })); + } + + if("authorityCertSerialNumber" in asn1.result) + { + asn1.result["authorityCertSerialNumber"].id_block.tag_class = 1; // UNIVERSAL + asn1.result["authorityCertSerialNumber"].id_block.tag_number = 2; // INTEGER + + this.authorityCertSerialNumber = asn1.result["authorityCertSerialNumber"]; + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.AuthorityKeyIdentifier.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + if("keyIdentifier" in this) + { + var value = this.keyIdentifier; + + value.id_block.tag_class = 3; // CONTEXT-SPECIFIC + value.id_block.tag_number = 0; // [0] + + output_array.push(value); + } + + if("authorityCertIssuer" in this) + { + var issuer_array = new Array(); + + for(var i = 0; i < this.authorityCertIssuer.length; i++) + issuer_array.push(this.authorityCertIssuer[i].toSchema()); + + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [new in_window.org.pkijs.asn1.SEQUENCE({ + value: issuer_array + })] + })); + } + + if("authorityCertSerialNumber" in this) + { + var value = this.authorityCertSerialNumber; + + value.id_block.tag_class = 3; // CONTEXT-SPECIFIC + value.id_block.tag_number = 2; // [2] + + output_array.push(value); + } + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.AuthorityKeyIdentifier.prototype.toJSON = + function() + { + var _object = {}; + + if("keyIdentifier" in this) + _object.keyIdentifier = this.keyIdentifier.toJSON(); + + if("authorityCertIssuer" in this) + { + _object.authorityCertIssuer = new Array(); + + for(var i = 0; i < this.authorityCertIssuer.length; i++) + _object.authorityCertIssuer.push(this.authorityCertIssuer[i].toJSON()); + } + + if("authorityCertSerialNumber" in this) + _object.authorityCertSerialNumber = this.authorityCertSerialNumber.toJSON(); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "PrivateKeyUsagePeriod" type of extension + //************************************************************************************** + in_window.org.pkijs.simpl.x509.PrivateKeyUsagePeriod = + function() + { + // #region Internal properties of the object + // OPTIONAL this.notBefore - new Date() + // OPTIONAL this.notAfter - new Date() + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.x509.PrivateKeyUsagePeriod.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + if("notBefore" in arguments[0]) + this.notBefore = arguments[0].notBefore; + + if("notAfter" in arguments[0]) + this.notAfter = arguments[0].notAfter; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.PrivateKeyUsagePeriod.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.x509.PrivateKeyUsagePeriod({ + names: { + notBefore: "notBefore", + notAfter: "notAfter" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for PrivateKeyUsagePeriod"); + // #endregion + + // #region Get internal properties from parsed schema + if("notBefore" in asn1.result) + { + var localNotBefore = new in_window.org.pkijs.asn1.GENERALIZEDTIME(); + localNotBefore.fromBuffer(asn1.result["notBefore"].value_block.value_hex); + this.notBefore = localNotBefore.toDate(); + } + + if("notAfter" in asn1.result) + { + var localNotAfter = new in_window.org.pkijs.asn1.GENERALIZEDTIME({ value_hex: asn1.result["notAfter"].value_block.value_hex }); + localNotAfter.fromBuffer(asn1.result["notAfter"].value_block.value_hex); + this.notAfter = localNotAfter.toDate(); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.PrivateKeyUsagePeriod.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + if("notBefore" in this) + output_array.push(new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value_hex: (new in_window.org.pkijs.asn1.GENERALIZEDTIME({ value_date: this.notBefore })).value_block.value_hex + })); + + if("notAfter" in this) + output_array.push(new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value_hex: (new in_window.org.pkijs.asn1.GENERALIZEDTIME({ value_date: this.notAfter })).value_block.value_hex + })); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.PrivateKeyUsagePeriod.prototype.toJSON = + function() + { + var _object = {}; + + if("notBefore" in this) + _object.notBefore = this.notBefore; + + if("notAfter" in this) + _object.notAfter = this.notAfter; + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "IssuerAltName" and "SubjectAltName" types of extension + //************************************************************************************** + in_window.org.pkijs.simpl.x509.AltName = + function() + { + // #region Internal properties of the object + this.altNames = new Array(); //Array of GeneralName + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.x509.AltName.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.altNames = arguments[0].altNames || new Array(); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.AltName.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.x509.AltName({ + names: { + altNames: "altNames" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for AltName"); + // #endregion + + // #region Get internal properties from parsed schema + if("altNames" in asn1.result) + { + var altNames_array = asn1.result["altNames"]; + + for(var i = 0; i < altNames_array.length; i++) + this.altNames.push(new in_window.org.pkijs.simpl.GENERAL_NAME({ schema: altNames_array[i] })); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.AltName.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + for(var i = 0; i < this.altNames.length; i++) + output_array.push(this.altNames[i].toSchema()); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.AltName.prototype.toJSON = + function() + { + var _object = { + altNames: new Array() + }; + + for(var i = 0; i < this.altNames.length; i++) + _object.altNames.push(this.altNames[i].toJSON()); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "SubjectDirectoryAttributes" type of extension + //************************************************************************************** + in_window.org.pkijs.simpl.x509.SubjectDirectoryAttributes = + function() + { + // #region Internal properties of the object + this.attributes = new Array(); // Array of "simpl.ATTRIBUTE" + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.x509.SubjectDirectoryAttributes.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.attributes = arguments[0].attributes || new Array(); // Array of "simpl.ATTRIBUTE" + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.SubjectDirectoryAttributes.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.x509.SubjectDirectoryAttributes({ + names: { + attributes: "attributes" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for SubjectDirectoryAttributes"); + // #endregion + + // #region Get internal properties from parsed schema + var attrs = asn1.result["attributes"]; + + for(var i = 0; i < attrs.length; i++) + this.attributes.push(new in_window.org.pkijs.simpl.ATTRIBUTE({ schema: attrs[i] })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.SubjectDirectoryAttributes.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + for(var i = 0; i < this.attributes.length; i++) + output_array.push(this.attributes[i].toSchema()); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.SubjectDirectoryAttributes.prototype.toJSON = + function() + { + var _object = { + attributes: new Array() + }; + + for(var i = 0; i < this.attributes.length; i++) + _object.attributes.push(this.attributes[i].toJSON()); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "PolicyMapping" type + //************************************************************************************** + in_window.org.pkijs.simpl.x509.PolicyMapping = + function() + { + // #region Internal properties of the object + this.issuerDomainPolicy = ""; + this.subjectDomainPolicy = ""; + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.x509.PolicyMapping.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.issuerDomainPolicy = arguments[0].issuerDomainPolicy || ""; + this.subjectDomainPolicy = arguments[0].subjectDomainPolicy || ""; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.PolicyMapping.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.x509.PolicyMapping({ + names: { + issuerDomainPolicy: "issuerDomainPolicy", + subjectDomainPolicy: "subjectDomainPolicy" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for PolicyMapping"); + // #endregion + + // #region Get internal properties from parsed schema + this.issuerDomainPolicy = asn1.result["issuerDomainPolicy"].value_block.toString(); + this.subjectDomainPolicy = asn1.result["subjectDomainPolicy"].value_block.toString(); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.PolicyMapping.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + new in_window.org.pkijs.asn1.OID({ value: this.issuerDomainPolicy }), + new in_window.org.pkijs.asn1.OID({ value: this.subjectDomainPolicy }) + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.PolicyMapping.prototype.toJSON = + function() + { + return { + issuerDomainPolicy: this.issuerDomainPolicy, + subjectDomainPolicy: this.subjectDomainPolicy + }; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "PolicyMappings" type of extension + //************************************************************************************** + in_window.org.pkijs.simpl.x509.PolicyMappings = + function() + { + // #region Internal properties of the object + this.mappings = new Array(); // Array of "simpl.x509.PolicyMapping" + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.x509.PolicyMappings.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.mappings = arguments[0].mappings || new Array(); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.PolicyMappings.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.x509.PolicyMappings({ + names: { + mappings: "mappings" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for PolicyMappings"); + // #endregion + + // #region Get internal properties from parsed schema + var maps = asn1.result["mappings"]; + + for(var i = 0; i < maps.length; i++) + this.mappings.push(new in_window.org.pkijs.simpl.x509.PolicyMapping({ schema: maps[i] })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.PolicyMappings.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + for(var i = 0; i < this.mappings.length; i++) + output_array.push(this.mappings[i].toSchema()); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.PolicyMappings.prototype.toJSON = + function() + { + var _object = { + mappings: new Array() + }; + + for(var i = 0; i < this.mappings.length; i++) + _object.mappings.push(this.mappings[i].toJSON()); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "GeneralSubtree" type + //************************************************************************************** + in_window.org.pkijs.simpl.x509.GeneralSubtree = + function() + { + // #region Internal properties of the object + this.base = new in_window.org.pkijs.simpl.GENERAL_NAME(); + // OPTIONAL this.minimum // in_window.org.pkijs.asn1.INTEGER + // OPTIONAL this.maximum // in_window.org.pkijs.asn1.INTEGER + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.x509.GeneralSubtree.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.base = arguments[0].base || new in_window.org.pkijs.simpl.GENERAL_NAME(); + + if("minimum" in arguments[0]) + this.minimum = arguments[0].minimum; + + if("maximum" in arguments[0]) + this.maximum = arguments[0].maximum; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.GeneralSubtree.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.x509.GeneralSubtree({ + names: { + base: { + names: { + block_name: "base" + } + }, + minimum: "minimum", + maximum: "maximum" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for "); + // #endregion + + // #region Get internal properties from parsed schema + this.base = new in_window.org.pkijs.simpl.GENERAL_NAME({ schema: asn1.result["base"] }); + + if("minimum" in asn1.result) + { + if(asn1.result["minimum"].value_block.is_hex_only) + this.minimum = asn1.result["minimum"]; + else + this.minimum = asn1.result["minimum"].value_block.value_dec; + } + + if("maximum" in asn1.result) + { + if(asn1.result["maximum"].value_block.is_hex_only) + this.maximum = asn1.result["maximum"]; + else + this.maximum = asn1.result["maximum"].value_block.value_dec; + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.GeneralSubtree.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + output_array.push(this.base.toSchema()); + + if("minimum" in this) + { + var value_minimum = 0; + + if(this.minimum instanceof in_window.org.pkijs.asn1.INTEGER) + value_minimum = this.minimum; + else + value_minimum = new in_window.org.pkijs.asn1.INTEGER({ value: this.minimum }); + + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [value_minimum] + })); + } + + if("maximum" in this) + { + var value_maximum = 0; + + if(this.maximum instanceof in_window.org.pkijs.asn1.INTEGER) + value_maximum = this.maximum; + else + value_maximum = new in_window.org.pkijs.asn1.INTEGER({ value: this.maximum }); + + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [value_maximum] + })); + } + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.GeneralSubtree.prototype.toJSON = + function() + { + var _object = { + base: this.base.toJSON() + }; + + if("minimum" in this) + { + if((typeof this.minimum) === "number") + _object.minimum = this.minimum; + else + _object.minimum = this.minimum.toJSON(); + } + + if("maximum" in this) + { + if((typeof this.maximum) === "number") + _object.maximum = this.maximum; + else + _object.maximum = this.maximum.toJSON(); + } + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "NameConstraints" type of extension + //************************************************************************************** + in_window.org.pkijs.simpl.x509.NameConstraints = + function() + { + // #region Internal properties of the object + // OPTIONAL this.permittedSubtrees - Array of "simpl.x509.GeneralSubtree" + // OPTIONAL this.excludedSubtrees - Array of "simpl.x509.GeneralSubtree" + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.x509.NameConstraints.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + if("permittedSubtrees" in arguments[0]) + this.permittedSubtrees = arguments[0].permittedSubtrees; + + if("excludedSubtrees" in arguments[0]) + this.excludedSubtrees = arguments[0].excludedSubtrees; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.NameConstraints.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.x509.NameConstraints({ + names: { + permittedSubtrees: "permittedSubtrees", + excludedSubtrees: "excludedSubtrees" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for NameConstraints"); + // #endregion + + // #region Get internal properties from parsed schema + if("permittedSubtrees" in asn1.result) + { + this.permittedSubtrees = new Array(); + var permited_array = asn1.result["permittedSubtrees"]; + + for(var i = 0; i < permited_array.length; i++) + this.permittedSubtrees.push(new in_window.org.pkijs.simpl.x509.GeneralSubtree({ schema: permited_array[i] })); + } + + if("excludedSubtrees" in asn1.result) + { + this.excludedSubtrees = new Array(); + var excluded_array = asn1.result["excludedSubtrees"]; + + for(var i = 0; i < excluded_array.length; i++) + this.excludedSubtrees.push(new in_window.org.pkijs.simpl.x509.GeneralSubtree({ schema: excluded_array[i] })); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.NameConstraints.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + if("permittedSubtrees" in this) + { + var permited_array = new Array(); + + for(var i = 0; i < this.permittedSubtrees.length; i++) + permited_array.push(this.permittedSubtrees[i].toSchema()); + + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [new in_window.org.pkijs.asn1.SEQUENCE({ + value: permited_array + })] + })); + } + + if("excludedSubtrees" in this) + { + var excluded_array = new Array(); + + for(var i = 0; i < this.excludedSubtrees.length; i++) + excluded_array.push(this.excludedSubtrees[i].toSchema()); + + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [new in_window.org.pkijs.asn1.SEQUENCE({ + value: excluded_array + })] + })); + } + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.NameConstraints.prototype.toJSON = + function() + { + var _object = {}; + + if("permittedSubtrees" in this) + { + _object.permittedSubtrees = new Array(); + + for(var i = 0; i < this.permittedSubtrees.length; i++) + _object.permittedSubtrees.push(this.permittedSubtrees[i].toJSON()); + } + + if("excludedSubtrees" in this) + { + _object.excludedSubtrees = new Array(); + + for(var i = 0; i < this.excludedSubtrees.length; i++) + _object.excludedSubtrees.push(this.excludedSubtrees[i].toJSON()); + } + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "BasicConstraints" type of extension + //************************************************************************************** + in_window.org.pkijs.simpl.x509.BasicConstraints = + function() + { + // #region Internal properties of the object + // OPTIONAL this.cA - boolean value + // OPTIONAL this.pathLenConstraint - integer value + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.x509.BasicConstraints.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + if("cA" in arguments[0]) + this.cA = arguments[0].cA; + + if("pathLenConstraint" in arguments[0]) + this.pathLenConstraint = arguments[0].pathLenConstraint; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.BasicConstraints.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.x509.BasicConstraints({ + names: { + cA: "cA", + pathLenConstraint: "pathLenConstraint" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for BasicConstraints"); + // #endregion + + // #region Get internal properties from parsed schema + if("cA" in asn1.result) + this.cA = asn1.result["cA"].value_block.value; + + if("pathLenConstraint" in asn1.result) + this.pathLenConstraint = asn1.result["pathLenConstraint"].value_block.value_dec; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.BasicConstraints.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + if("cA" in this) + output_array.push(new in_window.org.pkijs.asn1.BOOLEAN({ value: this.cA })); + + if("pathLenConstraint" in this) + output_array.push(new in_window.org.pkijs.asn1.INTEGER({ value: this.pathLenConstraint })); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.BasicConstraints.prototype.toJSON = + function() + { + var _object = {}; + + if("cA" in this) + _object.cA = this.cA; + + if("pathLenConstraint" in this) + _object.pathLenConstraint = this.pathLenConstraint; + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "PolicyQualifierInfo" type + //************************************************************************************** + in_window.org.pkijs.simpl.x509.PolicyQualifierInfo = + function() + { + // #region Internal properties of the object + this.policyQualifierId = ""; + this.qualifier = new in_window.org.pkijs.asn1.ANY(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.x509.PolicyQualifierInfo.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.policyQualifierId = arguments[0].policyQualifierId || ""; + this.qualifier = arguments[0].qualifier || new in_window.org.pkijs.asn1.ANY(); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.PolicyQualifierInfo.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.x509.PolicyQualifierInfo({ + names: { + policyQualifierId: "policyQualifierId", + qualifier: "qualifier" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for PolicyQualifierInfo"); + // #endregion + + // #region Get internal properties from parsed schema + this.policyQualifierId = asn1.result["policyQualifierId"].value_block.toString(); + this.qualifier = asn1.result["qualifier"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.PolicyQualifierInfo.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + new in_window.org.pkijs.asn1.OID({ value: this.policyQualifierId }), + this.qualifier + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.PolicyQualifierInfo.prototype.toJSON = + function() + { + return { + policyQualifierId: this.policyQualifierId, + qualifier: this.qualifier.toJSON() + }; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "PolicyInformation" type + //************************************************************************************** + in_window.org.pkijs.simpl.x509.PolicyInformation = + function() + { + // #region Internal properties of the object + this.policyIdentifier = ""; + // OPTIONAL this.policyQualifiers = new Array(); // Array of "simpl.x509.PolicyQualifierInfo" + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.x509.PolicyInformation.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.policyIdentifier = arguments[0].policyIdentifier || ""; + + if("policyQualifiers" in arguments[0]) + this.policyQualifiers = arguments[0].policyQualifiers; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.PolicyInformation.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.x509.PolicyInformation({ + names: { + policyIdentifier: "policyIdentifier", + policyQualifiers: "policyQualifiers" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for PolicyInformation"); + // #endregion + + // #region Get internal properties from parsed schema + this.policyIdentifier = asn1.result["policyIdentifier"].value_block.toString(); + + if("policyQualifiers" in asn1.result) + { + this.policyQualifiers = new Array(); + var qualifiers = asn1.result["policyQualifiers"]; + + for(var i = 0; i < qualifiers.length; i++) + this.policyQualifiers.push(new in_window.org.pkijs.simpl.x509.PolicyQualifierInfo({ schema: qualifiers[i] })); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.PolicyInformation.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + output_array.push(new in_window.org.pkijs.asn1.OID({ value: this.policyIdentifier })); + + if("policyQualifiers" in this) + { + var qualifiers = new Array(); + + for(var i = 0; i < this.policyQualifiers.length; i++) + qualifiers.push(this.policyQualifiers[i].toSchema()); + + output_array.push(new in_window.org.pkijs.asn1.SEQUENCE({ + value: qualifiers + })); + } + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.PolicyInformation.prototype.toJSON = + function() + { + var _object = { + policyIdentifier: this.policyIdentifier + }; + + if("policyQualifiers" in this) + { + _object.policyQualifiers = new Array(); + + for(var i = 0; i < this.policyQualifiers.length; i++) + _object.policyQualifiers.push(this.policyQualifiers[i].toJSON()); + } + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "CertificatePolicies" type of extension + //************************************************************************************** + in_window.org.pkijs.simpl.x509.CertificatePolicies = + function() + { + // #region Internal properties of the object + this.certificatePolicies = new Array(); // Array of "simpl.x509.PolicyInformation" + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.x509.CertificatePolicies.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.certificatePolicies = arguments[0].certificatePolicies || new Array(); // Array of "simpl.x509.PolicyInformation" + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.CertificatePolicies.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.x509.CertificatePolicies({ + names: { + certificatePolicies: "certificatePolicies" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for CertificatePolicies"); + // #endregion + + // #region Get internal properties from parsed schema + var policies = asn1.result["certificatePolicies"]; + + for(var i = 0; i < policies.length; i++) + this.certificatePolicies.push(new in_window.org.pkijs.simpl.x509.PolicyInformation({ schema: policies[i] })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.CertificatePolicies.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + for(var i = 0; i < this.certificatePolicies.length; i++) + output_array.push(this.certificatePolicies[i].toSchema()); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.CertificatePolicies.prototype.toJSON = + function() + { + var _object = { + certificatePolicies: new Array() + }; + + for(var i = 0; i < this.certificatePolicies.length; i++) + _object.certificatePolicies.push(this.certificatePolicies[i].toJSON()); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "PolicyConstraints" type of extension + //************************************************************************************** + in_window.org.pkijs.simpl.x509.PolicyConstraints = + function() + { + // #region Internal properties of the object + // OPTIONAL this.requireExplicitPolicy = 0; + // OPTIONAL this.inhibitPolicyMapping = 0; + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.x509.PolicyConstraints.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.requireExplicitPolicy = arguments[0].requireExplicitPolicy || 0; + this.inhibitPolicyMapping = arguments[0].inhibitPolicyMapping || 0; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.PolicyConstraints.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.x509.PolicyConstraints({ + names: { + requireExplicitPolicy: "requireExplicitPolicy", + inhibitPolicyMapping: "inhibitPolicyMapping" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for PolicyConstraints"); + // #endregion + + // #region Get internal properties from parsed schema + if("requireExplicitPolicy" in asn1.result) + { + var field1 = asn1.result["requireExplicitPolicy"]; + + field1.id_block.tag_class = 1; // UNIVERSAL + field1.id_block.tag_number = 2; // INTEGER + + var ber1 = field1.toBER(false); + var int1 = in_window.org.pkijs.fromBER(ber1); + + this.requireExplicitPolicy = int1.result.value_block.value_dec; + } + + if("inhibitPolicyMapping" in asn1.result) + { + var field2 = asn1.result["inhibitPolicyMapping"]; + + field2.id_block.tag_class = 1; // UNIVERSAL + field2.id_block.tag_number = 2; // INTEGER + + var ber2 = field2.toBER(false); + var int2 = in_window.org.pkijs.fromBER(ber2); + + this.inhibitPolicyMapping = int2.result.value_block.value_dec; + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.PolicyConstraints.prototype.toSchema = + function() + { + // #region Create correct values for output sequence + var output_array = new Array(); + + if("requireExplicitPolicy" in this) + { + var int1 = new in_window.org.pkijs.asn1.INTEGER({ value: this.requireExplicitPolicy }); + + int1.id_block.tag_class = 3; // CONTEXT-SPECIFIC + int1.id_block.tag_number = 0; // [0] + + output_array.push(int1); + } + + if("inhibitPolicyMapping" in this) + { + var int2 = new in_window.org.pkijs.asn1.INTEGER({ value: this.inhibitPolicyMapping }); + + int2.id_block.tag_class = 3; // CONTEXT-SPECIFIC + int2.id_block.tag_number = 1; // [1] + + output_array.push(int2); + } + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.PolicyConstraints.prototype.toJSON = + function() + { + var _object = {}; + + if("requireExplicitPolicy" in this) + _object.requireExplicitPolicy = this.requireExplicitPolicy; + + if("inhibitPolicyMapping" in this) + _object.inhibitPolicyMapping = this.inhibitPolicyMapping; + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "ExtKeyUsage" type of extension + //************************************************************************************** + in_window.org.pkijs.simpl.x509.ExtKeyUsage = + function() + { + // #region Internal properties of the object + this.keyPurposes = new Array(); // Array of strings (OIDs value for key purposes) + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.x509.ExtKeyUsage.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.keyPurposes = arguments[0].keyPurposes || new Array(); // Array of strings (OIDs value for key purposes) + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.ExtKeyUsage.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.x509.ExtKeyUsage({ + names: { + keyPurposes: "keyPurposes" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for ExtKeyUsage"); + // #endregion + + // #region Get internal properties from parsed schema + var purposes = asn1.result["keyPurposes"]; + + for(var i = 0; i < purposes.length; i++) + this.keyPurposes.push(purposes[i].value_block.toString()); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.ExtKeyUsage.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + for(var i = 0; i < this.keyPurposes.length; i++) + output_array.push(new in_window.org.pkijs.asn1.OID({ value: this.keyPurposes[i] })); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.ExtKeyUsage.prototype.toJSON = + function() + { + var _object = { + keyPurposes: new Array() + }; + + for(var i = 0; i < this.keyPurposes.length; i++) + _object.keyPurposes.push(this.keyPurposes[i]); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "DistributionPoint" type + //************************************************************************************** + in_window.org.pkijs.simpl.x509.DistributionPoint = + function() + { + // #region Internal properties of the object + // OPTIONAL this.distributionPoint // Array of "simpl.GENERAL_NAME" or a value of "simpl.RDN" type + // OPTIONAL this.reasons // BITSTRING value + // OPTIONAL this.cRLIssuer // Array of "simpl.GENERAL_NAME" + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.x509.DistributionPoint.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + if("distributionPoint" in arguments[0]) + this.distributionPoint = arguments[0].distributionPoint; + + if("reasons" in arguments[0]) + this.reasons = arguments[0].reasons; + + if("cRLIssuer" in arguments[0]) + this.cRLIssuer = arguments[0].cRLIssuer; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.DistributionPoint.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.x509.DistributionPoint({ + names: { + distributionPoint: "distributionPoint", + distributionPoint_names: "distributionPoint_names", + reasons: "reasons", + cRLIssuer: "cRLIssuer", + cRLIssuer_names: "cRLIssuer_names" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for DistributionPoint"); + // #endregion + + // #region Get internal properties from parsed schema + if("distributionPoint" in asn1.result) + { + if(asn1.result["distributionPoint"].id_block.tag_number == 0) // GENERAL_NAMES variant + { + this.distributionPoint = new Array(); + var names = asn1.result["distributionPoint_names"]; + + for(var i = 0; i < names.length; i++) + this.distributionPoint.push(new in_window.org.pkijs.simpl.GENERAL_NAME({ schema: names[i] })); + } + + if(asn1.result["distributionPoint"].id_block.tag_number == 1) // RDN variant + { + asn1.result["distributionPoint"].id_block.tag_class = 1; // UNIVERSAL + asn1.result["distributionPoint"].id_block.tag_number = 16; // SEQUENCE + + this.distributionPoint = new in_window.org.pkijs.simpl.RDN({ schema: asn1.result["distributionPoint"] }); + } + } + + if("reasons" in asn1.result) + this.reasons = new in_window.org.pkijs.asn1.BITSTRING({ value_hex: asn1.result["reasons"].value_block.value_hex }); + + if("cRLIssuer" in asn1.result) + { + this.cRLIssuer = new Array(); + var crl_names = asn1.result["cRLIssuer_names"]; + + for(var i = 0; i < crl_names; i++) + this.cRLIssuer.push(new in_window.org.pkijs.simpl.GENERAL_NAME({ schema: crl_names[i] })); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.DistributionPoint.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + if("distributionPoint" in this) + { + var internalValue; + + if(this.distributionPoint instanceof Array) + { + var namesArray = new Array(); + + for(var i = 0; i < this.distributionPoint.length; i++) + namesArray.push(this.distributionPoint[i].toSchema()); + + internalValue = new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: namesArray + }); + } + else + { + internalValue = new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value: [this.distributionPoint.toSchema()] + }); + } + + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [internalValue] + })); + } + + if("reasons" in this) + { + output_array.push(new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value_hex: this.reasons.value_block.value_hex + })); + } + + if("cRLIssuer" in this) + { + var value = new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 2 // [2] + } + }); + + for(var i = 0; i < this.cRLIssuer.length; i++) + value.value_block.value.push(this.cRLIssuer[i].toSchema()); + + output_array.push(value); + } + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.DistributionPoint.prototype.toJSON = + function() + { + var _object = {}; + + if("distributionPoint" in this) + { + if(this.distributionPoint instanceof Array) + { + _object.distributionPoint = new Array(); + + for(var i = 0; i < this.distributionPoint.length; i++) + _object.distributionPoint.push(this.distributionPoint[i].toJSON()); + } + else + _object.distributionPoint = this.distributionPoint.toJSON(); + } + + if("reasons" in this) + _object.reasons = this.reasons.toJSON(); + + if("cRLIssuer" in this) + { + _object.cRLIssuer = new Array(); + + for(var i = 0; i < this.cRLIssuer.length; i++) + _object.cRLIssuer.push(this.cRLIssuer[i].toJSON()); + } + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "CRLDistributionPoints" type of extension + //************************************************************************************** + in_window.org.pkijs.simpl.x509.CRLDistributionPoints = + function() + { + // #region Internal properties of the object + this.distributionPoints = new Array(); // Array of "simpl.x509.DistributionPoint" + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.x509.CRLDistributionPoints.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.distributionPoints = arguments[0].distributionPoints || new Array(); // Array of "simpl.x509.DistributionPoint" + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.CRLDistributionPoints.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.x509.CRLDistributionPoints({ + names: { + distributionPoints: "distributionPoints" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for CRLDistributionPoints"); + // #endregion + + // #region Get internal properties from parsed schema + var points = asn1.result["distributionPoints"]; + + for(var i = 0; i < points.length; i++) + this.distributionPoints.push(new in_window.org.pkijs.simpl.x509.DistributionPoint({ schema: points[i] })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.CRLDistributionPoints.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + for(var i = 0; i < this.distributionPoints.length; i++) + output_array.push(this.distributionPoints[i].toSchema()); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.CRLDistributionPoints.prototype.toJSON = + function() + { + var _object = { + distributionPoints: new Array() + }; + + for(var i = 0; i < this.distributionPoints.length; i++) + _object.distributionPoints.push(this.distributionPoints[i].toJSON()); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "AccessDescription" type + //************************************************************************************** + in_window.org.pkijs.simpl.x509.AccessDescription = + function() + { + // #region Internal properties of the object + this.accessMethod = ""; + this.accessLocation = new in_window.org.pkijs.simpl.GENERAL_NAME(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.x509.AccessDescription.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.accessMethod = arguments[0].accessMethod || ""; + this.accessLocation = arguments[0].accessLocation || new in_window.org.pkijs.simpl.GENERAL_NAME(); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.AccessDescription.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.x509.AccessDescription({ + names: { + accessMethod: "accessMethod", + accessLocation: { + names: { + block_name: "accessLocation" + } + } + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for AccessDescription"); + // #endregion + + // #region Get internal properties from parsed schema + this.accessMethod = asn1.result["accessMethod"].value_block.toString(); + this.accessLocation = new in_window.org.pkijs.simpl.GENERAL_NAME({ schema: asn1.result["accessLocation"] }); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.AccessDescription.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + new in_window.org.pkijs.asn1.OID({ value: this.accessMethod }), + this.accessLocation.toSchema() + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.AccessDescription.prototype.toJSON = + function() + { + return { + accessMethod: this.accessMethod, + accessLocation: this.accessLocation.toJSON() + }; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "AuthorityInfoAccess" and "SubjectInfoAccess" types of extension + //************************************************************************************** + in_window.org.pkijs.simpl.x509.InfoAccess = + function() + { + // #region Internal properties of the object + this.accessDescriptions = new Array(); // Array of "simpl.x509.AccessDescription" + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.x509.InfoAccess.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.accessDescriptions = arguments[0].accessDescriptions || new Array(); // Array of "simpl.x509.DistributionPoint" + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.InfoAccess.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.x509.InfoAccess({ + names: { + accessDescriptions: "accessDescriptions" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for InfoAccess"); + // #endregion + + // #region Get internal properties from parsed schema + var descriptions = asn1.result["accessDescriptions"]; + + for(var i = 0; i < descriptions.length; i++) + this.accessDescriptions.push(new in_window.org.pkijs.simpl.x509.AccessDescription({ schema: descriptions[i] })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.InfoAccess.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + for(var i = 0; i < this.accessDescriptions.length; i++) + output_array.push(this.accessDescriptions[i].toSchema()); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.InfoAccess.prototype.toJSON = + function() + { + var _object = { + accessDescriptions: new Array() + }; + + for(var i = 0; i < this.accessDescriptions.length; i++) + _object.accessDescriptions.push(this.accessDescriptions[i].toJSON()); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "IssuingDistributionPoint" type of extension + //************************************************************************************** + in_window.org.pkijs.simpl.x509.IssuingDistributionPoint = + function() + { + // #region Internal properties of the object + // OPTIONAL this.distributionPoint // Array of "simpl.GENERAL_NAME" or a value of "simpl.RDN" type + // OPTIONAL this.onlyContainsUserCerts // BOOLEAN flag + // OPTIONAL this.onlyContainsCACerts // BOOLEAN flag + // OPTIONAL this.onlySomeReasons // BITSTRING + // OPTIONAL this.indirectCRL // BOOLEAN flag + // OPTIONAL this.onlyContainsAttributeCerts // BOOLEAN flag + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.x509.IssuingDistributionPoint.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + if("distributionPoint" in arguments[0]) + this.distributionPoint = arguments[0].distributionPoint; + + if("onlyContainsUserCerts" in arguments[0]) + this.onlyContainsUserCerts = arguments[0].onlyContainsUserCerts; + + if("onlyContainsCACerts" in arguments[0]) + this.onlyContainsCACerts = arguments[0].onlyContainsCACerts; + + if("onlySomeReasons" in arguments[0]) + this.onlySomeReasons = arguments[0].onlySomeReasons; + + if("indirectCRL" in arguments[0]) + this.indirectCRL = arguments[0].indirectCRL; + + if("onlyContainsAttributeCerts" in arguments[0]) + this.onlyContainsAttributeCerts = arguments[0].onlyContainsAttributeCerts; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.IssuingDistributionPoint.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.x509.IssuingDistributionPoint({ + names: { + distributionPoint: "distributionPoint", + distributionPoint_names: "distributionPoint_names", + onlyContainsUserCerts: "onlyContainsUserCerts", + onlyContainsCACerts: "onlyContainsCACerts", + onlySomeReasons: "onlySomeReasons", + indirectCRL: "indirectCRL", + onlyContainsAttributeCerts: "onlyContainsAttributeCerts" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for IssuingDistributionPoint"); + // #endregion + + // #region Get internal properties from parsed schema + if("distributionPoint" in asn1.result) + { + if(asn1.result["distributionPoint"].id_block.tag_number == 0) // GENERAL_NAMES variant + { + this.distributionPoint = new Array(); + var names = asn1.result["distributionPoint_names"]; + + for(var i = 0; i < names.length; i++) + this.distributionPoint.push(new in_window.org.pkijs.simpl.GENERAL_NAME({ schema: names[i] })); + } + + if(asn1.result["distributionPoint"].id_block.tag_number == 1) // RDN variant + { + asn1.result["distributionPoint"].id_block.tag_class = 1; // UNIVERSAL + asn1.result["distributionPoint"].id_block.tag_number = 16; // SEQUENCE + + this.distributionPoint = new in_window.org.pkijs.simpl.RDN({ schema: asn1.result["distributionPoint"] }); + } + } + + if("onlyContainsUserCerts" in asn1.result) + { + var view = new Uint8Array(asn1.result["onlyContainsUserCerts"].value_block.value_hex); + this.onlyContainsUserCerts = (view[0] !== 0x00); + } + + if("onlyContainsCACerts" in asn1.result) + { + var view = new Uint8Array(asn1.result["onlyContainsCACerts"].value_block.value_hex); + this.onlyContainsCACerts = (view[0] !== 0x00); + } + + if("onlySomeReasons" in asn1.result) + { + var view = new Uint8Array(asn1.result["onlySomeReasons"].value_block.value_hex); + this.onlySomeReasons = view[0]; + } + + if("indirectCRL" in asn1.result) + { + var view = new Uint8Array(asn1.result["indirectCRL"].value_block.value_hex); + this.indirectCRL = (view[0] !== 0x00); + } + + if("onlyContainsAttributeCerts" in asn1.result) + { + var view = new Uint8Array(asn1.result["onlyContainsAttributeCerts"].value_block.value_hex); + this.onlyContainsAttributeCerts = (view[0] !== 0x00); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.IssuingDistributionPoint.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + if("distributionPoint" in this) + { + var value; + + if(this.distributionPoint instanceof Array) + { + value = new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + } + }); + + for(var i = 0; i < this.distributionPoint.length; i++) + value.value_block.value.push(this.distributionPoint[i].toSchema()); + } + else + { + value = this.distributionPoint.toSchema(); + + value.id_block.tag_class = 3; // CONTEXT - SPECIFIC + value.id_block.tag_number = 1; // [1] + } + + output_array.push(value); + } + + if("onlyContainsUserCerts" in this) + { + var buffer = new ArrayBuffer(1); + var view = new Uint8Array(buffer); + + view[0] = (this.onlyContainsUserCerts === false) ? 0x00 : 0xFF; + + output_array.push(new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value_hex: buffer + })); + } + + if("onlyContainsCACerts" in this) + { + var buffer = new ArrayBuffer(1); + var view = new Uint8Array(buffer); + + view[0] = (this.onlyContainsCACerts === false) ? 0x00 : 0xFF; + + output_array.push(new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 2 // [2] + }, + value_hex: buffer + })); + } + + if("onlySomeReasons" in this) + { + var buffer = new ArrayBuffer(1); + var view = new Uint8Array(buffer); + + view[0] = this.onlySomeReasons; + + output_array.push(new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 3 // [3] + }, + value_hex: buffer + })); + } + + if("indirectCRL" in this) + { + var buffer = new ArrayBuffer(1); + var view = new Uint8Array(buffer); + + view[0] = (this.indirectCRL === false) ? 0x00 : 0xFF; + + output_array.push(new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 4 // [4] + }, + value_hex: buffer + })); + } + + if("onlyContainsAttributeCerts" in this) + { + var buffer = new ArrayBuffer(1); + var view = new Uint8Array(buffer); + + view[0] = (this.onlyContainsAttributeCerts === false) ? 0x00 : 0xFF; + + output_array.push(new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 5 // [5] + }, + value_hex: buffer + })); + } + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.x509.IssuingDistributionPoint.prototype.toJSON = + function() + { + var _object = {}; + + if("distributionPoint" in this) + { + if(this.distributionPoint instanceof Array) + { + _object.distributionPoint = new Array(); + + for(var i = 0; i < this.distributionPoint.length; i++) + _object.distributionPoint.push(this.distributionPoint[i].toJSON()); + } + else + _object.distributionPoint = this.distributionPoint.toJSON(); + } + + if("onlyContainsUserCerts" in this) + _object.onlyContainsUserCerts = this.onlyContainsUserCerts; + + if("onlyContainsCACerts" in this) + _object.onlyContainsCACerts = this.onlyContainsCACerts; + + if("onlySomeReasons" in this) + _object.onlySomeReasons = this.onlySomeReasons; + + if("indirectCRL" in this) + _object.indirectCRL = this.indirectCRL; + + if("onlyContainsAttributeCerts" in this) + _object.onlyContainsAttributeCerts = this.onlyContainsAttributeCerts; + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "Extension" type + //************************************************************************************** + in_window.org.pkijs.simpl.EXTENSION = + function() + { + // #region Internal properties of the object + this.extnID = ""; + this.critical = false; + this.extnValue = new in_window.org.pkijs.asn1.OCTETSTRING(); + + // OPTIONAL this.parsedValue - Parsed "extnValue" in case of well-known "extnID" + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.EXTENSION.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.extnID = (arguments[0].extnID || ""); + this.critical = (arguments[0].critical || false); + if("extnValue" in arguments[0]) + this.extnValue = new in_window.org.pkijs.asn1.OCTETSTRING({ value_hex: arguments[0].extnValue }); + else + this.extnValue = new in_window.org.pkijs.asn1.OCTETSTRING(); + + if("parsedValue" in arguments[0]) + this.parsedValue = arguments[0].parsedValue; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.EXTENSION.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.EXTENSION({ + names: { + extnID: "extnID", + critical: "critical", + extnValue: "extnValue" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for EXTENSION"); + // #endregion + + // #region Get internal properties from parsed schema + this.extnID = asn1.result.extnID.value_block.toString(); + if("critical" in asn1.result) + this.critical = asn1.result.critical.value_block.value; + this.extnValue = asn1.result.extnValue; + + // #region Get "parsedValue" for well-known extensions + asn1 = in_window.org.pkijs.fromBER(this.extnValue.value_block.value_hex); + if(asn1.offset === (-1)) + return; + + switch(this.extnID) + { + case "2.5.29.9": // SubjectDirectoryAttributes + this.parsedValue = new in_window.org.pkijs.simpl.x509.SubjectDirectoryAttributes({ schema: asn1.result }); + break; + case "2.5.29.14": // SubjectKeyIdentifier + this.parsedValue = asn1.result; // Should be just a simple OCTETSTRING + break; + case "2.5.29.15": // KeyUsage + this.parsedValue = asn1.result; // Should be just a simple BITSTRING + break; + case "2.5.29.16": // PrivateKeyUsagePeriod + this.parsedValue = new in_window.org.pkijs.simpl.x509.PrivateKeyUsagePeriod({ schema: asn1.result }); + break; + case "2.5.29.17": // SubjectAltName + case "2.5.29.18": // IssuerAltName + this.parsedValue = new in_window.org.pkijs.simpl.x509.AltName({ schema: asn1.result }); + break; + case "2.5.29.19": // BasicConstraints + this.parsedValue = new in_window.org.pkijs.simpl.x509.BasicConstraints({ schema: asn1.result }); + break; + case "2.5.29.20": // CRLNumber + case "2.5.29.27": // BaseCRLNumber (delta CRL indicator) + this.parsedValue = asn1.result; // Should be just a simple INTEGER + break; + case "2.5.29.21": // CRLReason + this.parsedValue = asn1.result; // Should be just a simple ENUMERATED + break; + case "2.5.29.24": // InvalidityDate + this.parsedValue = asn1.result; // Should be just a simple GeneralizedTime + break; + case "2.5.29.28": // IssuingDistributionPoint + this.parsedValue = new in_window.org.pkijs.simpl.x509.IssuingDistributionPoint({ schema: asn1.result }); + break; + case "2.5.29.29": // CertificateIssuer + this.parsedValue = new in_window.org.pkijs.simpl.GENERAL_NAMES({ schema: asn1.result }); // Should be just a simple + break; + case "2.5.29.30": // NameConstraints + this.parsedValue = new in_window.org.pkijs.simpl.x509.NameConstraints({ schema: asn1.result }); + break; + case "2.5.29.31": // CRLDistributionPoints + case "2.5.29.46": // FreshestCRL + this.parsedValue = new in_window.org.pkijs.simpl.x509.CRLDistributionPoints({ schema: asn1.result }); + break; + case "2.5.29.32": // CertificatePolicies + this.parsedValue = new in_window.org.pkijs.simpl.x509.CertificatePolicies({ schema: asn1.result }); + break; + case "2.5.29.33": // PolicyMappings + this.parsedValue = new in_window.org.pkijs.simpl.x509.PolicyMappings({ schema: asn1.result }); + break; + case "2.5.29.35": // AuthorityKeyIdentifier + this.parsedValue = new in_window.org.pkijs.simpl.x509.AuthorityKeyIdentifier({ schema: asn1.result }); + break; + case "2.5.29.36": // PolicyConstraints + this.parsedValue = new in_window.org.pkijs.simpl.x509.PolicyConstraints({ schema: asn1.result }); + break; + case "2.5.29.37": // ExtKeyUsage + this.parsedValue = new in_window.org.pkijs.simpl.x509.ExtKeyUsage({ schema: asn1.result }); + break; + case "2.5.29.54": // InhibitAnyPolicy + this.parsedValue = asn1.result; // Should be just a simple INTEGER + break; + case "1.3.6.1.5.5.7.1.1": // AuthorityInfoAccess + case "1.3.6.1.5.5.7.1.11": // SubjectInfoAccess + this.parsedValue = new in_window.org.pkijs.simpl.x509.InfoAccess({ schema: asn1.result }); + break; + default:; + } + // #endregion + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.EXTENSION.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + output_array.push(new in_window.org.pkijs.asn1.OID({ value: this.extnID })); + + if(this.critical) + output_array.push(new in_window.org.pkijs.asn1.BOOLEAN({ value: this.critical })); + + output_array.push(this.extnValue); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.EXTENSION.prototype.toJSON = + function() + { + var _object = { + extnID: this.extnID, + critical: this.critical, + extnValue: this.extnValue.toJSON() + }; + + if("parsedValue" in this) + _object.parsedValue = this.parsedValue.toJSON(); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "Extensions" type (sequence of many Extension) + //************************************************************************************** + in_window.org.pkijs.simpl.EXTENSIONS = + function() + { + // #region Internal properties of the object + this.extensions_array = new Array(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.EXTENSIONS.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + this.extensions_array = (arguments[0].extensions_array || (new Array())); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.EXTENSIONS.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.EXTENSIONS({ + names: { + extensions: "extensions" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for EXTENSIONS"); + // #endregion + + // #region Get internal properties from parsed schema + for(var i = 0; i < asn1.result.extensions.length; i++) + this.extensions_array.push(new in_window.org.pkijs.simpl.EXTENSION({ schema: asn1.result.extensions[i] })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.EXTENSIONS.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + var extension_schemas = new Array(); + + for(var i = 0; i < this.extensions_array.length; i++) + extension_schemas.push(this.extensions_array[i].toSchema()); + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: extension_schemas + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.EXTENSIONS.prototype.toJSON = + function() + { + var _object = { + extensions_array: new Array() + }; + + for(var i = 0; i < this.extensions_array.length; i++) + _object.extensions_array.push(this.extensions_array[i].toJSON()); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for X.509 v3 certificate (RFC5280) + //************************************************************************************** + in_window.org.pkijs.simpl.CERT = + function() + { + // #region Internal properties of the object + // #region Properties from certificate TBS part + this.tbs = new ArrayBuffer(0); // Encoded value of certificate TBS (need to have it for certificate validation) + + // OPTIONAL this.version = 0; + this.serialNumber = new in_window.org.pkijs.asn1.INTEGER(); // Might be a very long integer value + this.signature = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); // Signature algorithm from certificate TBS part + this.issuer = new in_window.org.pkijs.simpl.RDN(); + this.notBefore = new in_window.org.pkijs.simpl.TIME(); + this.notAfter = new in_window.org.pkijs.simpl.TIME(); + this.subject = new in_window.org.pkijs.simpl.RDN(); + this.subjectPublicKeyInfo = new in_window.org.pkijs.simpl.PUBLIC_KEY_INFO(); + // OPTIONAL this.issuerUniqueID = new ArrayBuffer(0); // IMPLICIT bistring value + // OPTIONAL this.subjectUniqueID = new ArrayBuffer(0); // IMPLICIT bistring value + // OPTIONAL this.extensions = new Array(); // Array of "simpl.EXTENSION" + // #endregion + + // #region Properties from certificate major part + this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); // Signature algorithm from certificate major part + this.signatureValue = new in_window.org.pkijs.asn1.BITSTRING(); + // #endregion + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.CERT.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + // #region Properties from certificate TBS part + this.tbs = arguments[0].tbs || new ArrayBuffer(0); + + if("version" in arguments[0]) + this.version = arguments[0].version; + this.serialNumber = arguments[0].serialNumber || new in_window.org.pkijs.asn1.INTEGER(); // Might be a very long integer value + this.signature = arguments[0].signature || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); // Signature algorithm from certificate TBS part + this.issuer = arguments[0].issuer || new in_window.org.pkijs.simpl.RDN(); + this.notBefore = arguments[0].not_before || new in_window.org.pkijs.simpl.TIME(); + this.notAfter = arguments[0].not_after || new in_window.org.pkijs.simpl.TIME(); + this.subject = arguments[0].subject || new in_window.org.pkijs.simpl.RDN(); + this.subjectPublicKeyInfo = arguments[0].subjectPublicKeyInfo || new in_window.org.pkijs.simpl.PUBLIC_KEY_INFO(); + if("issuerUniqueID" in arguments[0]) + this.issuerUniqueID = arguments[0].issuerUniqueID; + if("subjectUniqueID" in arguments[0]) + this.subjectUniqueID = arguments[0].subjectUniqueID; + if("extensions" in arguments[0]) + this.extensions = arguments[0].extensions; + // #endregion + + // #region Properties from certificate major part + this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); // Signature algorithm from certificate major part + this.signatureValue = new in_window.org.pkijs.asn1.BITSTRING(); + // #endregion + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CERT.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.CERT({ + names: { + tbsCertificate: { + names: { + extensions: { + names: { + extensions: "tbsCertificate.extensions" + } + } + } + } + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for CERT"); + // #endregion + + // #region Get internal properties from parsed schema + this.tbs = asn1.result["tbsCertificate"].value_before_decode; + + if("tbsCertificate.version" in asn1.result) + this.version = asn1.result["tbsCertificate.version"].value_block.value_dec; + this.serialNumber = asn1.result["tbsCertificate.serialNumber"]; + this.signature = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["tbsCertificate.signature"] }); + this.issuer = new in_window.org.pkijs.simpl.RDN({ schema: asn1.result["tbsCertificate.issuer"] }); + this.notBefore = new in_window.org.pkijs.simpl.TIME({ schema: asn1.result["tbsCertificate.notBefore"] }); + this.notAfter = new in_window.org.pkijs.simpl.TIME({ schema: asn1.result["tbsCertificate.notAfter"] }); + this.subject = new in_window.org.pkijs.simpl.RDN({ schema: asn1.result["tbsCertificate.subject"] }); + this.subjectPublicKeyInfo = new in_window.org.pkijs.simpl.PUBLIC_KEY_INFO({ schema: asn1.result["tbsCertificate.subjectPublicKeyInfo"] }); + if("tbsCertificate.issuerUniqueID" in asn1.result) + this.issuerUniqueID = asn1.result["tbsCertificate.issuerUniqueID"].value_block.value_hex; + if("tbsCertificate.subjectUniqueID" in asn1.result) + this.issuerUniqueID = asn1.result["tbsCertificate.subjectUniqueID"].value_block.value_hex; + if("tbsCertificate.extensions" in asn1.result) + { + this.extensions = new Array(); + + var extensions = asn1.result["tbsCertificate.extensions"]; + + for(var i = 0; i < extensions.length; i++) + this.extensions.push(new in_window.org.pkijs.simpl.EXTENSION({ schema: extensions[i] })); + } + + this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["signatureAlgorithm"] }); + this.signatureValue = asn1.result["signatureValue"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CERT.prototype.encodeTBS = + function() + { + /// Create ASN.1 schema for existing values of TBS part for the certificate + + // #region Create array for output sequence + var output_array = new Array(); + + if("version" in this) + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [ + new in_window.org.pkijs.asn1.INTEGER({ value: this.version }) // EXPLICIT integer value + ] + })); + + output_array.push(this.serialNumber); + output_array.push(this.signature.toSchema()); + output_array.push(this.issuer.toSchema()); + + output_array.push(new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + this.notBefore.toSchema(), + this.notAfter.toSchema() + ] + })); + + output_array.push(this.subject.toSchema()); + output_array.push(this.subjectPublicKeyInfo.toSchema()); + + if("issuerUniqueID" in this) + output_array.push(new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 1 // [1] + }, + value_hex: this.issuerUniqueID + })); + if("subjectUniqueID" in this) + output_array.push(new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 2 // [2] + }, + value_hex: this.subjectUniqueID + })); + + if("subjectUniqueID" in this) + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 3 // [3] + }, + value: [this.extensions.toSchema()] + })); + + if("extensions" in this) + { + var extensions = new Array(); + + for(var i = 0; i < this.extensions.length; i++) + extensions.push(this.extensions[i].toSchema()); + + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 3 // [3] + }, + value: [new in_window.org.pkijs.asn1.SEQUENCE({ + value: extensions + })] + })); + } + // #endregion + + // #region Create and return output sequence + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CERT.prototype.toSchema = + function(encodeFlag) + { + /// If param equal to false then create TBS schema via decoding stored value. In othe case create TBS schema via assembling from TBS parts. + + if(typeof encodeFlag === "undefined") + encodeFlag = false; + + var tbs_schema = {}; + + // #region Decode stored TBS value + if(encodeFlag === false) + { + if(this.tbs.length === 0) // No stored certificate TBS part + return in_window.org.pkijs.schema.CERT().value[0]; + + var tbs_asn1 = in_window.org.pkijs.fromBER(this.tbs); + + tbs_schema = tbs_asn1.result; + } + // #endregion + // #region Create TBS schema via assembling from TBS parts + else + tbs_schema = in_window.org.pkijs.simpl.CERT.prototype.encodeTBS.call(this); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + tbs_schema, + this.signatureAlgorithm.toSchema(), + this.signatureValue + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CERT.prototype.verify = + function() + { + /// !!! Works well in Chrome dev versions only (April 2014th) !!! + /// Returns a new Promise object (in case of error), or a result of "crypto.subtle.veryfy" function + + // #region Global variables + var sequence = Promise.resolve(); + + var subjectPublicKeyInfo = {}; + + var signature = this.signatureValue; + var tbs = this.tbs; + + var _this = this; + // #endregion + + // #region Set correct "subjectPublicKeyInfo" value + if(arguments[0] instanceof Object) + { + if("issuerCertificate" in arguments[0]) // Must be of type "simpl.CERT" + subjectPublicKeyInfo = arguments[0].issuerCertificate.subjectPublicKeyInfo; + } + else + { + if(this.issuer.isEqual(this.subject)) // Self-signed certificate + subjectPublicKeyInfo = this.subjectPublicKeyInfo; + } + + if((subjectPublicKeyInfo instanceof in_window.org.pkijs.simpl.PUBLIC_KEY_INFO) === false) + return Promise.reject("Please provide issuer certificate as a parameter"); + // #endregion + + // #region Get a "crypto" extension + var crypto = in_window.org.pkijs.getCrypto(); + if(typeof crypto == "undefined") + return Promise.reject("Unable to create WebCrypto object"); + // #endregion + + // #region Find signer's hashing algorithm + var sha_algorithm = in_window.org.pkijs.getHashAlgorithm(this.signatureAlgorithm); + if(sha_algorithm === "") + return Promise.reject("Unsupported signature algorithm: " + _this.signatureAlgorithm.algorithm_id); + // #endregion + + // #region Importing public key + sequence = sequence.then( + function() + { + // #region Get information about public key algorithm and default parameters for import + var algorithmObject = in_window.org.pkijs.getAlgorithmByOID(_this.signatureAlgorithm.algorithm_id); + if(("name" in algorithmObject) === false) + return Promise.reject("Unsupported public key algorithm: " + _this.signatureAlgorithm.algorithm_id); + + var algorithm_name = algorithmObject.name; + + var algorithm = in_window.org.pkijs.getAlgorithmParameters(algorithm_name, "importkey"); + if("hash" in algorithm.algorithm) + algorithm.algorithm.hash.name = sha_algorithm; + + // #region Special case for ECDSA + if(algorithm_name === "ECDSA") + { + // #region Get information about named curve + if((subjectPublicKeyInfo.algorithm.algorithm_params instanceof in_window.org.pkijs.asn1.OID) === false) + return Promise.reject("Incorrect type for ECDSA public key parameters"); + + var curveObject = in_window.org.pkijs.getAlgorithmByOID(subjectPublicKeyInfo.algorithm.algorithm_params.value_block.toString()); + if(("name" in curveObject) === false) + return Promise.reject("Unsupported named curve algorithm: " + subjectPublicKeyInfo.algorithm.algorithm_params.value_block.toString()); + // #endregion + + algorithm.algorithm.namedCurve = curveObject.name; + } + // #endregion + // #endregion + + var publicKeyInfo_schema = subjectPublicKeyInfo.toSchema(); + var publicKeyInfo_buffer = publicKeyInfo_schema.toBER(false); + var publicKeyInfo_view = new Uint8Array(publicKeyInfo_buffer); + + return crypto.importKey("spki", publicKeyInfo_view, algorithm.algorithm, true, algorithm.usages); + } + ); + // #endregion + + // #region Verify signature for the certificate + sequence = sequence.then( + function(publicKey) + { + // #region Get default algorithm parameters for verification + var algorithm = in_window.org.pkijs.getAlgorithmParameters(publicKey.algorithm.name, "verify"); + if("hash" in algorithm.algorithm) + algorithm.algorithm.hash.name = sha_algorithm; + // #endregion + + // #region Special case for ECDSA signatures + var signature_value = signature.value_block.value_hex; + + if(publicKey.algorithm.name === "ECDSA") + { + var asn1 = in_window.org.pkijs.fromBER(signature_value); + signature_value = in_window.org.pkijs.createECDSASignatureFromCMS(asn1.result); + } + // #endregion + + // #region Special case for RSA-PSS + if(publicKey.algorithm.name === "RSA-PSS") + { + var pssParameters; + + try + { + pssParameters = new in_window.org.pkijs.simpl.x509.RSASSA_PSS_params({ schema: _this.signatureAlgorithm.algorithm_params }); + } + catch(ex) + { + return Promise.reject(ex); + } + + if("saltLength" in pssParameters) + algorithm.algorithm.saltLength = pssParameters.saltLength; + else + algorithm.algorithm.saltLength = 20; + + var hash_algo = "SHA-1"; + + if("hashAlgorithm" in pssParameters) + { + var hashAlgorithm = in_window.org.pkijs.getAlgorithmByOID(pssParameters.hashAlgorithm.algorithm_id); + if(("name" in hashAlgorithm) === false) + return Promise.reject("Unrecognized hash algorithm: " + pssParameters.hashAlgorithm.algorithm_id); + + hash_algo = hashAlgorithm.name; + } + + algorithm.algorithm.hash.name = hash_algo; + } + // #endregion + + return crypto.verify(algorithm.algorithm, + publicKey, + new Uint8Array(signature_value), + new Uint8Array(tbs)); + } + ); + // #endregion + + return sequence; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CERT.prototype.sign = + function(privateKey, hashAlgorithm) + { + /// Private key for "subjectPublicKeyInfo" structure + /// Hashing algorithm. Default SHA-1 + + // #region Initial variables + var _this = this; + // #endregion + + // #region Get a private key from function parameter + if(typeof privateKey === "undefined") + return Promise.reject("Need to provide a private key for signing"); + // #endregion + + // #region Get hashing algorithm + if(typeof hashAlgorithm === "undefined") + hashAlgorithm = "SHA-1"; + else + { + // #region Simple check for supported algorithm + var oid = in_window.org.pkijs.getOIDByAlgorithm({ name: hashAlgorithm }); + if(oid === "") + return Promise.reject("Unsupported hash algorithm: " + hashAlgorithm); + // #endregion + } + // #endregion + + // #region Get a "default parameters" for current algorithm + var defParams = in_window.org.pkijs.getAlgorithmParameters(privateKey.algorithm.name, "sign"); + defParams.algorithm.hash.name = hashAlgorithm; + // #endregion + + // #region Fill internal structures base on "privateKey" and "hashAlgorithm" + switch(privateKey.algorithm.name.toUpperCase()) + { + case "RSASSA-PKCS1-V1_5": + case "ECDSA": + _this.signature.algorithm_id = in_window.org.pkijs.getOIDByAlgorithm(defParams.algorithm); + _this.signatureAlgorithm.algorithm_id = _this.signature.algorithm_id; + break; + case "RSA-PSS": + { + // #region Set "saltLength" as a length (in octets) of hash function result + switch(hashAlgorithm.toUpperCase()) + { + case "SHA-256": + defParams.algorithm.saltLength = 32; + break; + case "SHA-384": + defParams.algorithm.saltLength = 48; + break; + case "SHA-512": + defParams.algorithm.saltLength = 64; + break; + default:; + } + // #endregion + + // #region Fill "RSASSA_PSS_params" object + var paramsObject = {}; + + if(hashAlgorithm.toUpperCase() !== "SHA-1") + { + var hashAlgorithmOID = in_window.org.pkijs.getOIDByAlgorithm({ name: hashAlgorithm }); + if(hashAlgorithmOID === "") + return Promise.reject("Unsupported hash algorithm: " + hashAlgorithm); + + paramsObject.hashAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: hashAlgorithmOID, + algorithm_params: new in_window.org.pkijs.asn1.NULL() + }); + + paramsObject.maskGenAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: "1.2.840.113549.1.1.8", // MGF1 + algorithm_params: paramsObject.hashAlgorithm.toSchema() + }) + } + + if(defParams.algorithm.saltLength !== 20) + paramsObject.saltLength = defParams.algorithm.saltLength; + + var pssParameters = new in_window.org.pkijs.simpl.x509.RSASSA_PSS_params(paramsObject); + // #endregion + + // #region Automatically set signature algorithm + _this.signature = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: "1.2.840.113549.1.1.10", + algorithm_params: pssParameters.toSchema() + }); + _this.signatureAlgorithm = _this.signature; // Must be the same + // #endregion + } + break; + default: + return Promise.reject("Unsupported signature algorithm: " + privateKey.algorithm.name); + } + // #endregion + + // #region Create TBS data for signing + _this.tbs = in_window.org.pkijs.simpl.CERT.prototype.encodeTBS.call(this).toBER(false); + // #endregion + + // #region Get a "crypto" extension + var crypto = in_window.org.pkijs.getCrypto(); + if(typeof crypto == "undefined") + return Promise.reject("Unable to create WebCrypto object"); + // #endregion + + // #region Signing TBS data on provided private key + return crypto.sign(defParams.algorithm, + privateKey, + new Uint8Array(_this.tbs)).then( + function(result) + { + // #region Special case for ECDSA algorithm + if(defParams.algorithm.name === "ECDSA") + result = in_window.org.pkijs.createCMSECDSASignature(result); + // #endregion + + _this.signatureValue = new in_window.org.pkijs.asn1.BITSTRING({ value_hex: result }); + }, + function(error) + { + return Promise.reject("Signing error: " + error); + } + ); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CERT.prototype.getPublicKey = + function() + { + /// Importing public key for current certificate + + // #region Initial variables + var algorithm; + // #endregion + + // #region Get a "crypto" extension + var crypto = in_window.org.pkijs.getCrypto(); + if(typeof crypto == "undefined") + return Promise.reject("Unable to create WebCrypto object"); + // #endregion + + // #region Find correct algorithm for imported public key + if(arguments[0] instanceof Object) + { + if("algorithm" in arguments[0]) + algorithm = arguments[0].algorithm; + else + return Promise.reject("Absent mandatory parameter \"algorithm\""); + } + else + { + // #region Find signer's hashing algorithm + var sha_algorithm = in_window.org.pkijs.getHashAlgorithm(this.signatureAlgorithm); + if(sha_algorithm === "") + return Promise.reject("Unsupported signature algorithm: " + _this.signatureAlgorithm.algorithm_id); + // #endregion + + // #region Get information about public key algorithm and default parameters for import + var algorithmObject = in_window.org.pkijs.getAlgorithmByOID(this.signatureAlgorithm.algorithm_id); + if(("name" in algorithmObject) === false) + return Promise.reject("Unsupported public key algorithm: " + _this.signatureAlgorithm.algorithm_id); + + var algorithm_name = algorithmObject.name; + + algorithm = in_window.org.pkijs.getAlgorithmParameters(algorithm_name, "importkey"); + if("hash" in algorithm.algorithm) + algorithm.algorithm.hash.name = sha_algorithm; + + // #region Special case for ECDSA + if(algorithm_name === "ECDSA") + { + // #region Get information about named curve + if((this.subjectPublicKeyInfo.algorithm.algorithm_params instanceof in_window.org.pkijs.asn1.OID) === false) + return Promise.reject("Incorrect type for ECDSA public key parameters"); + + var curveObject = in_window.org.pkijs.getAlgorithmByOID(this.subjectPublicKeyInfo.algorithm.algorithm_params.value_block.toString()); + if(("name" in curveObject) === false) + return Promise.reject("Unsupported named curve algorithm: " + this.subjectPublicKeyInfo.algorithm.algorithm_params.value_block.toString()); + // #endregion + + algorithm.algorithm.namedCurve = curveObject.name; + } + // #endregion + // #endregion + } + // #endregion + + // #region Get neccessary values from internal fields for current certificate + var publicKeyInfo_schema = this.subjectPublicKeyInfo.toSchema(); + var publicKeyInfo_buffer = publicKeyInfo_schema.toBER(false); + var publicKeyInfo_view = new Uint8Array(publicKeyInfo_buffer); + // #endregion + + return crypto.importKey("spki", publicKeyInfo_view, algorithm.algorithm, true, algorithm.usages); + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CERT.prototype.getKeyHash = + function() + { + /// Get SHA-1 hash value for subject public key + + // #region Get a "crypto" extension + var crypto = in_window.org.pkijs.getCrypto(); + if(typeof crypto == "undefined") + return Promise.reject("Unable to create WebCrypto object"); + // #endregion + + return crypto.digest({ name: "sha-1" }, new Uint8Array(this.subjectPublicKeyInfo.subjectPublicKey.value_block.value_hex)); + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CERT.prototype.toJSON = + function() + { + var _object = { + tbs: in_window.org.pkijs.bufferToHexCodes(this.tbs, 0, this.tbs.byteLength), + serialNumber: this.serialNumber.toJSON(), + signature: this.signature.toJSON(), + issuer: this.issuer.toJSON(), + notBefore: this.notBefore.toJSON(), + notAfter: this.notAfter.toJSON(), + subject: this.subject.toJSON(), + subjectPublicKeyInfo: this.subjectPublicKeyInfo.toJSON(), + signatureAlgorithm: this.signatureAlgorithm.toJSON(), + signatureValue: this.signatureValue.toJSON() + }; + + if("version" in this) + _object.version = this.version; + + if("issuerUniqueID" in this) + _object.issuerUniqueID = in_window.org.pkijs.bufferToHexCodes(this.issuerUniqueID, 0, this.issuerUniqueID.byteLength); + + if("subjectUniqueID" in this) + _object.subjectUniqueID = in_window.org.pkijs.bufferToHexCodes(this.subjectUniqueID, 0, this.subjectUniqueID.byteLength); + + if("extensions" in this) + { + _object.extensions = new Array(); + + for(var i = 0; i < this.extensions.length; i++) + _object.extensions.push(this.extensions[i].toJSON()); + } + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "revoked certificate" type (to use in CRL) + //************************************************************************************** + in_window.org.pkijs.simpl.REV_CERT = + function() + { + // #region Internal properties of the object + this.userCertificate = new in_window.org.pkijs.asn1.INTEGER(); + this.revocationDate = new in_window.org.pkijs.simpl.TIME(); + // OPTIONAL this.crlEntryExtensions = new Array(); // Array of "in_window.org.pkijs.simpl.EXTENSION"); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.REV_CERT.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.userCertificate = arguments[0].userCertificate || new in_window.org.pkijs.asn1.INTEGER(); + this.revocationDate = arguments[0].revocationDate || new in_window.org.pkijs.simpl.TIME(); + if("crlEntryExtensions" in arguments[0]) + this.crlEntryExtensions = arguments[0].crlEntryExtensions; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.REV_CERT.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + new in_window.org.pkijs.asn1.INTEGER({ name: "userCertificate" }), + in_window.org.pkijs.schema.TIME({ + names: { + utcTimeName: "revocationDate", + generalTimeName: "revocationDate" + } + }), + in_window.org.pkijs.schema.EXTENSIONS({ + names: { + block_name: "crlEntryExtensions" + } + }, true) + ] + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for REV_CERT"); + // #endregion + + // #region Get internal properties from parsed schema + this.userCertificate = asn1.result["userCertificate"]; + this.revocationDate = new in_window.org.pkijs.simpl.TIME({ schema: asn1.result["revocationDate"] }); + + if("crlEntryExtensions" in asn1.result) + { + this.crlEntryExtensions = new Array(); + var exts = asn1.result["crlEntryExtensions"].value_block.value; + + for(var i = 0; i < exts.length; i++) + this.crlEntryExtensions.push(new in_window.org.pkijs.simpl.EXTENSION({ schema: exts[i] })); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.REV_CERT.prototype.toSchema = + function() + { + // #region Create array for output sequence + var sequence_array = new Array(); + sequence_array.push(this.userCertificate); + sequence_array.push(this.revocationDate.toSchema()); + + if("crlEntryExtensions" in this) + { + var exts = new Array(); + + for(var i = 0; i < this.crlEntryExtensions.length; i++) + exts.push(this.crlEntryExtensions[i].toSchema()); + + sequence_array.push(new in_window.org.pkijs.asn1.SEQUENCE({ value: exts })); + } + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: sequence_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.REV_CERT.prototype.toJSON = + function() + { + var _object = { + userCertificate: this.userCertificate.toJSON(), + revocationDate: this.revocationDate.toJSON + }; + + if("crlEntryExtensions" in this) + { + _object.crlEntryExtensions = new Array(); + + for(var i = 0; i < this.crlEntryExtensions.length; i++) + _object.crlEntryExtensions.push(this.crlEntryExtensions[i].toJSON()); + } + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for X.509 CRL (Certificate Revocation List)(RFC5280) + //************************************************************************************** + in_window.org.pkijs.simpl.CRL = + function() + { + // #region Internal properties of the object + // #region Properties from CRL TBS part + this.tbs = new ArrayBuffer(0); + + // OPTIONAL this.version = 1; + this.signature = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.issuer = new in_window.org.pkijs.simpl.RDN(); + this.thisUpdate = new in_window.org.pkijs.simpl.TIME(); + // OPTIONAL this.nextUpdate = new in_window.org.pkijs.simpl.TIME(); + // OPTIONAL this.revokedCertificates = new Array(); // Array of REV_CERT objects + // OPTIONAL this.crlExtensions = new Array(); // Array of in_window.org.pkijs.simpl.EXTENSION(); + // #endregion + + // #region Properties from CRL major part + this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.signatureValue = new in_window.org.pkijs.asn1.BITSTRING(); + // #endregion + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.CRL.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + // #region Properties from CRL TBS part + this.tbs = arguments[0].tbs || new ArrayBuffer(0); + + if("version" in arguments[0]) + this.version = arguments[0].version; + this.signature = arguments[0].signature || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.issuer = arguments[0].issuer || new in_window.org.pkijs.simpl.RDN(); + this.thisUpdate = arguments[0].thisUpdate || new in_window.org.pkijs.simpl.TIME(); + if("nextUpdate" in arguments[0]) + this.nextUpdate = arguments[0].nextUpdate; + if("revokedCertificates" in arguments[0]) + this.revokedCertificates = arguments[0].revokedCertificates; + if("crlExtensions" in arguments[0]) + this.crlExtensions = arguments[0].crlExtensions; + // #endregion + + // #region Properties from CRL major part + this.signatureAlgorithm = arguments[0].signatureAlgorithm || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.signatureValue = arguments[0].signatureValue || new in_window.org.pkijs.asn1.BITSTRING(); + // #endregion + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CRL.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.CRL() + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for CRL"); + // #endregion + + // #region Get internal properties from parsed schema + this.tbs = asn1.result["tbsCertList"].value_before_decode; + + if("tbsCertList.version" in asn1.result) + this.version = asn1.result["tbsCertList.version"].value_block.value_dec; + this.signature = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["tbsCertList.signature"] }); + this.issuer = new in_window.org.pkijs.simpl.RDN({ schema: asn1.result["tbsCertList.issuer"] }); + this.thisUpdate = new in_window.org.pkijs.simpl.TIME({ schema: asn1.result["tbsCertList.thisUpdate"] }); + if("tbsCertList.nextUpdate" in asn1.result) + this.nextUpdate = new in_window.org.pkijs.simpl.TIME({ schema: asn1.result["tbsCertList.nextUpdate"] }); + if("tbsCertList.revokedCertificates" in asn1.result) + { + this.revokedCertificates = new Array(); + + var rev_certs = asn1.result["tbsCertList.revokedCertificates"]; + for(var i = 0; i < rev_certs.length; i++) + this.revokedCertificates.push(new in_window.org.pkijs.simpl.REV_CERT({ schema: rev_certs[i] })); + } + if("tbsCertList.extensions" in asn1.result) + { + this.crlExtensions = new Array(); + var exts = asn1.result["tbsCertList.extensions"].value_block.value; + + for(var i = 0; i < exts.length; i++) + this.crlExtensions.push(new in_window.org.pkijs.simpl.EXTENSION({ schema: exts[i] })); + } + + this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["signatureAlgorithm"] }); + this.signatureValue = asn1.result["signatureValue"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CRL.prototype.encodeTBS = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + if("version" in this) + output_array.push(new in_window.org.pkijs.asn1.INTEGER({ value: this.version })); + + output_array.push(this.signature.toSchema()); + output_array.push(this.issuer.toSchema()); + output_array.push(this.thisUpdate.toSchema()); + + if("nextUpdate" in this) + output_array.push(this.nextUpdate.toSchema()); + + if("revokedCertificates" in this) + { + var rev_certificates = new Array(); + + for(var i = 0; i < this.revokedCertificates.length; i++) + rev_certificates.push(this.revokedCertificates[i].toSchema()); + + output_array.push(new in_window.org.pkijs.asn1.SEQUENCE({ + value: rev_certificates + })); + } + + if("crlExtensions" in this) + { + var extensions = new Array(); + + for(var j = 0; j < this.crlExtensions.length; j++) + extensions.push(this.crlExtensions[j].toSchema()); + + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: [ + new in_window.org.pkijs.asn1.SEQUENCE({ + value: extensions + }) + ] + })); + } + // #endregion + + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CRL.prototype.toSchema = + function(encodeFlag) + { + /// If param equal to false then create TBS schema via decoding stored value. In othe case create TBS schema via assembling from TBS parts. + + // #region Check "encodeFlag" + if(typeof encodeFlag === "undefined") + encodeFlag = false; + // #endregion + + // #region Decode stored TBS value + var tbs_schema; + + if(encodeFlag === false) + { + if(this.tbs.length === 0) // No stored TBS part + return in_window.org.pkijs.schema.CRL(); + + tbs_schema = in_window.org.pkijs.fromBER(this.tbs).result; + } + // #endregion + // #region Create TBS schema via assembling from TBS parts + else + tbs_schema = in_window.org.pkijs.simpl.CRL.prototype.encodeTBS.call(this); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + tbs_schema, + this.signatureAlgorithm.toSchema(), + this.signatureValue + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CRL.prototype.verify = + function() + { + // #region Global variables + var sequence = Promise.resolve(); + + var signature = this.signatureValue; + var tbs = this.tbs; + + var subjectPublicKeyInfo = -1; + + var _this = this; + // #endregion + + // #region Get information about CRL issuer certificate + if(arguments[0] instanceof Object) + { + if("issuerCertificate" in arguments[0]) // "issuerCertificate" must be of type "simpl.CERT" + { + subjectPublicKeyInfo = arguments[0].issuerCertificate.subjectPublicKeyInfo; + + // The CRL issuer name and "issuerCertificate" subject name are not equal + if(this.issuer.isEqual(arguments[0].issuerCertificate.subject) == false) + return Promise.resolve(false); + } + + // #region In case if there is only public key during verification + if("publicKeyInfo" in arguments[0]) + subjectPublicKeyInfo = arguments[0].publicKeyInfo; // Must be of type "org.pkijs.simpl.PUBLIC_KEY_INFO" + // #endregion + } + + if((subjectPublicKeyInfo instanceof in_window.org.pkijs.simpl.PUBLIC_KEY_INFO) === false) + return Promise.reject("Issuer's certificate must be provided as an input parameter"); + // #endregion + + // #region Check the CRL for unknown critical extensions + if("crlExtensions" in this) + { + for(var i = 0; i < this.crlExtensions.length; i++) + { + if(this.crlExtensions[i].critical) + { + // We can not be sure that unknown extension has no value for CRL signature + if(("parsedValue" in this.crlExtensions[i]) == false) + return Promise.resolve(false); + } + } + } + // #endregion + + // #region Get a "crypto" extension + var crypto = in_window.org.pkijs.getCrypto(); + if(typeof crypto == "undefined") + return Promise.reject("Unable to create WebCrypto object"); + // #endregion + + // #region Find signer's hashing algorithm + var sha_algorithm = in_window.org.pkijs.getHashAlgorithm(this.signatureAlgorithm); + if(sha_algorithm === "") + return Promise.reject("Unsupported signature algorithm: " + _this.signatureAlgorithm.algorithm_id); + // #endregion + + // #region Import public key + sequence = sequence.then( + function() + { + // #region Get information about public key algorithm and default parameters for import + var algorithmObject = in_window.org.pkijs.getAlgorithmByOID(_this.signature.algorithm_id); + if(("name" in algorithmObject) === "") + return Promise.reject("Unsupported public key algorithm: " + _this.signature.algorithm_id); + + var algorithm_name = algorithmObject.name; + + var algorithm = in_window.org.pkijs.getAlgorithmParameters(algorithm_name, "importkey"); + if("hash" in algorithm.algorithm) + algorithm.algorithm.hash.name = sha_algorithm; + + // #region Special case for ECDSA + if(algorithm_name === "ECDSA") + { + // #region Get information about named curve + if((subjectPublicKeyInfo.algorithm.algorithm_params instanceof in_window.org.pkijs.asn1.OID) === false) + return Promise.reject("Incorrect type for ECDSA public key parameters"); + + var curveObject = in_window.org.pkijs.getAlgorithmByOID(subjectPublicKeyInfo.algorithm.algorithm_params.value_block.toString()); + if(("name" in curveObject) === false) + return Promise.reject("Unsupported named curve algorithm: " + subjectPublicKeyInfo.algorithm.algorithm_params.value_block.toString()); + // #endregion + + algorithm.algorithm.namedCurve = curveObject.name; + } + // #endregion + // #endregion + + var publicKeyInfo_schema = subjectPublicKeyInfo.toSchema(); + var publicKeyInfo_buffer = publicKeyInfo_schema.toBER(false); + var publicKeyInfo_view = new Uint8Array(publicKeyInfo_buffer); + + return crypto.importKey("spki", + publicKeyInfo_view, + algorithm.algorithm, + true, + algorithm.usages); + } + ); + // #endregion + + // #region Verify signature for the certificate + sequence = sequence.then( + function(publicKey) + { + // #region Get default algorithm parameters for verification + var algorithm = in_window.org.pkijs.getAlgorithmParameters(publicKey.algorithm.name, "verify"); + if("hash" in algorithm.algorithm) + algorithm.algorithm.hash.name = sha_algorithm; + // #endregion + + // #region Special case for ECDSA signatures + var signature_value = signature.value_block.value_hex; + + if(publicKey.algorithm.name === "ECDSA") + { + var asn1 = in_window.org.pkijs.fromBER(signature_value); + signature_value = in_window.org.pkijs.createECDSASignatureFromCMS(asn1.result); + } + // #endregion + + // #region Special case for RSA-PSS + if(publicKey.algorithm.name === "RSA-PSS") + { + var pssParameters; + + try + { + pssParameters = new in_window.org.pkijs.simpl.x509.RSASSA_PSS_params({ schema: _this.signatureAlgorithm.algorithm_params }); + } + catch(ex) + { + return Promise.reject(ex); + } + + if("saltLength" in pssParameters) + algorithm.algorithm.saltLength = pssParameters.saltLength; + else + algorithm.algorithm.saltLength = 20; + + var hash_algo = "SHA-1"; + + if("hashAlgorithm" in pssParameters) + { + var hashAlgorithm = in_window.org.pkijs.getAlgorithmByOID(pssParameters.hashAlgorithm.algorithm_id); + if(("name" in hashAlgorithm) === false) + return Promise.reject("Unrecognized hash algorithm: " + pssParameters.hashAlgorithm.algorithm_id); + + hash_algo = hashAlgorithm.name; + } + + algorithm.algorithm.hash.name = hash_algo; + } + // #endregion + + return crypto.verify(algorithm.algorithm, + publicKey, + new Uint8Array(signature_value), + new Uint8Array(tbs)); + } + ); + // #endregion + + return sequence; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CRL.prototype.sign = + function(privateKey, hashAlgorithm) + { + /// Private key for "subjectPublicKeyInfo" structure + /// Hashing algorithm. Default SHA-1 + + // #region Initial variables + var _this = this; + // #endregion + + // #region Get a private key from function parameter + if(typeof privateKey === "undefined") + return Promise.reject("Need to provide a private key for signing"); + // #endregion + + // #region Get hashing algorithm + if(typeof hashAlgorithm === "undefined") + hashAlgorithm = "SHA-1"; + else + { + // #region Simple check for supported algorithm + var oid = in_window.org.pkijs.getOIDByAlgorithm({ name: hashAlgorithm }); + if(oid === "") + return Promise.reject("Unsupported hash algorithm: " + hashAlgorithm); + // #endregion + } + // #endregion + + // #region Get a "default parameters" for current algorithm + var defParams = in_window.org.pkijs.getAlgorithmParameters(privateKey.algorithm.name, "sign"); + defParams.algorithm.hash.name = hashAlgorithm; + // #endregion + + // #region Fill internal structures base on "privateKey" and "hashAlgorithm" + switch(privateKey.algorithm.name.toUpperCase()) + { + case "RSASSA-PKCS1-V1_5": + case "ECDSA": + _this.signature.algorithm_id = in_window.org.pkijs.getOIDByAlgorithm(defParams.algorithm); + _this.signatureAlgorithm.algorithm_id = _this.signature.algorithm_id; + break; + case "RSA-PSS": + { + // #region Set "saltLength" as a length (in octets) of hash function result + switch(hashAlgorithm.toUpperCase()) + { + case "SHA-256": + defParams.algorithm.saltLength = 32; + break; + case "SHA-384": + defParams.algorithm.saltLength = 48; + break; + case "SHA-512": + defParams.algorithm.saltLength = 64; + break; + default:; + } + // #endregion + + // #region Fill "RSASSA_PSS_params" object + var paramsObject = {}; + + if(hashAlgorithm.toUpperCase() !== "SHA-1") + { + var hashAlgorithmOID = in_window.org.pkijs.getOIDByAlgorithm({ name: hashAlgorithm }); + if(hashAlgorithmOID === "") + return Promise.reject("Unsupported hash algorithm: " + hashAlgorithm); + + paramsObject.hashAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: hashAlgorithmOID, + algorithm_params: new in_window.org.pkijs.asn1.NULL() + }); + + paramsObject.maskGenAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: "1.2.840.113549.1.1.8", // MGF1 + algorithm_params: paramsObject.hashAlgorithm.toSchema() + }) + } + + if(defParams.algorithm.saltLength !== 20) + paramsObject.saltLength = defParams.algorithm.saltLength; + + var pssParameters = new in_window.org.pkijs.simpl.x509.RSASSA_PSS_params(paramsObject); + // #endregion + + // #region Automatically set signature algorithm + _this.signature = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: "1.2.840.113549.1.1.10", + algorithm_params: pssParameters.toSchema() + }); + _this.signatureAlgorithm = _this.signature; // Must be the same + // #endregion + } + break; + default: + return Promise.reject("Unsupported signature algorithm: " + privateKey.algorithm.name); + } + // #endregion + + // #region Create TBS data for signing + _this.tbs = in_window.org.pkijs.simpl.CRL.prototype.encodeTBS.call(this).toBER(false); + // #endregion + + // #region Get a "crypto" extension + var crypto = in_window.org.pkijs.getCrypto(); + if(typeof crypto == "undefined") + return Promise.reject("Unable to create WebCrypto object"); + // #endregion + + // #region Signing TBS data on provided private key + return crypto.sign( + defParams.algorithm, + privateKey, + new Uint8Array(_this.tbs)). + then( + function(result) + { + // #region Special case for ECDSA algorithm + if(defParams.algorithm.name === "ECDSA") + result = in_window.org.pkijs.createCMSECDSASignature(result); + // #endregion + + _this.signatureValue = new in_window.org.pkijs.asn1.BITSTRING({ value_hex: result }); + }, + function(error) + { + return Promise.reject("Signing error: " + error); + } + ); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CRL.prototype.isCertificateRevoked = + function() + { + // #region Get input certificate + var certificate = {}; + + if(arguments[0] instanceof Object) + { + if("certificate" in arguments[0]) + certificate = arguments[0].certificate; + } + + if((certificate instanceof in_window.org.pkijs.simpl.CERT) === false) + return false; + // #endregion + + // #region Check that issuer of the input certificate is the same with issuer of this CRL + if(this.issuer.isEqual(certificate.issuer) === false) + return false; + // #endregion + + // #region Check that there are revoked certificates in this CRL + if(("revokedCertificates" in this) === false) + return false; + // #endregion + + // #region Search for input certificate in revoked certificates array + for(var i = 0; i < this.revokedCertificates.length; i++) + { + if(this.revokedCertificates[i].userCertificate.isEqual(certificate.serialNumber)) + return true; + } + // #endregion + + return false; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CRL.prototype.toJSON = + function() + { + var _object = { + tbs: in_window.org.pkijs.bufferToHexCodes(this.tbs, 0, this.tbs.byteLength), + signature: this.signature.toJSON(), + issuer: this.issuer.toJSON(), + thisUpdate: this.thisUpdate.toJSON(), + signatureAlgorithm: this.signatureAlgorithm.toJSON(), + signatureValue: this.signatureValue.toJSON() + }; + + if("version" in this) + _object.version = this.version; + + if("nextUpdate" in this) + _object.nextUpdate = this.nextUpdate.toJSON(); + + if("revokedCertificates" in this) + { + _object.revokedCertificates = new Array(); + + for(var i = 0; i < this.revokedCertificates.length; i++) + _object.revokedCertificates.push(this.revokedCertificates[i].toJSON()); + } + + if("crlExtensions" in this) + { + _object.crlExtensions = new Array(); + + for(var i = 0; i < this.crlExtensions.length; i++) + _object.crlExtensions.push(this.crlExtensions[i].toJSON()); + } + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for "Attribute" type + //************************************************************************************** + in_window.org.pkijs.simpl.ATTRIBUTE = + function() + { + // #region Internal properties of the object + this.type = ""; + this.values = new Array(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.ATTRIBUTE.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.type = arguments[0].type || ""; + this.values = arguments[0].values || new Array(); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ATTRIBUTE.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.ATTRIBUTE({ + names: { + type: "type", + values: "values" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for ATTRIBUTE"); + // #endregion + + // #region Get internal properties from parsed schema + this.type = asn1.result["type"].value_block.toString(); + this.values = asn1.result["values"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ATTRIBUTE.prototype.toSchema = + function() + { + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + new in_window.org.pkijs.asn1.OID({ value: this.type }), + new in_window.org.pkijs.asn1.SET({ + value: this.values + }) + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.ATTRIBUTE.prototype.toJSON = + function() + { + var _object = { + type: this.type, + values: new Array() + }; + + for(var i = 0; i < this.values.length; i++) + _object.values.push(this.values[i].toJSON()); + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for PKCS#10 certificate request + //************************************************************************************** + in_window.org.pkijs.simpl.PKCS10 = + function() + { + // #region Internal properties of the object + this.tbs = new ArrayBuffer(0); + + this.version = 0; + this.subject = new in_window.org.pkijs.simpl.RDN(); + this.subjectPublicKeyInfo = new in_window.org.pkijs.simpl.PUBLIC_KEY_INFO(); + // OPTIONAL this.attributes = new Array(); // Array of simpl.ATTRIBUTE objects + + this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); // Signature algorithm from certificate major part + this.signatureValue = new in_window.org.pkijs.asn1.BITSTRING(); + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.PKCS10.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.tbs = arguments[0].tbs || new ArrayBuffer(0); + + this.version = arguments[0].version || 0; + this.subject = arguments[0].subject || new in_window.org.pkijs.simpl.RDN(); + this.subjectPublicKeyInfo = arguments[0].subjectPublicKeyInfo || new in_window.org.pkijs.simpl.PUBLIC_KEY_INFO(); + + if("attributes" in arguments[0]) + this.attributes = arguments[0].attributes; + + this.signatureAlgorithm = arguments[0].signatureAlgorithm || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); // Signature algorithm from certificate major part + this.signatureValue = arguments[0].signatureValue || new in_window.org.pkijs.asn1.BITSTRING(); + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.PKCS10.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.PKCS10() + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for PKCS10"); + // #endregion + + // #region Get internal properties from parsed schema + this.tbs = asn1.result["CertificationRequestInfo"].value_before_decode; + + this.version = asn1.result["CertificationRequestInfo.version"].value_block.value_dec; + this.subject = new in_window.org.pkijs.simpl.RDN({ schema: asn1.result["CertificationRequestInfo.subject"] }); + this.subjectPublicKeyInfo = new in_window.org.pkijs.simpl.PUBLIC_KEY_INFO({ schema: asn1.result["CertificationRequestInfo.subjectPublicKeyInfo"] }); + if("CertificationRequestInfo.attributes" in asn1.result) + { + this.attributes = new Array(); + + var attrs = asn1.result["CertificationRequestInfo.attributes"]; + for(var i = 0; i < attrs.length; i++) + this.attributes.push(new in_window.org.pkijs.simpl.ATTRIBUTE({ schema: attrs[i] })); + } + + this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["signatureAlgorithm"] }); + this.signatureValue = asn1.result["signatureValue"]; + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.PKCS10.prototype.encodeTBS = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + output_array.push(new in_window.org.pkijs.asn1.INTEGER({ value: this.version })); + output_array.push(this.subject.toSchema()); + output_array.push(this.subjectPublicKeyInfo.toSchema()); + + if("attributes" in this) + { + var attributes = new Array(); + + for(var i = 0; i < this.attributes.length; i++) + attributes.push(this.attributes[i].toSchema()); + + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: attributes + })); + } + // #endregion + + return (new in_window.org.pkijs.asn1.SEQUENCE({ value: output_array })); + }; + //************************************************************************************** + in_window.org.pkijs.simpl.PKCS10.prototype.toSchema = + function(encodeFlag) + { + /// If param equal to false then create TBS schema via decoding stored value. In othe case create TBS schema via assembling from TBS parts. + + // #region Check "encodeFlag" + if(typeof encodeFlag === "undefined") + encodeFlag = false; + // #endregion + + // #region Decode stored TBS value + var tbs_schema; + + if(encodeFlag === false) + { + if(this.tbs.length === 0) // No stored TBS part + return in_window.org.pkijs.schema.PKCS10(); + + tbs_schema = in_window.org.pkijs.fromBER(this.tbs).result; + } + // #endregion + // #region Create TBS schema via assembling from TBS parts + else + tbs_schema = in_window.org.pkijs.simpl.PKCS10.prototype.encodeTBS.call(this); + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: [ + tbs_schema, + this.signatureAlgorithm.toSchema(), + this.signatureValue + ] + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.PKCS10.prototype.verify = + function() + { + /// !!! Works well in Chrome dev versions only (April 2014th) !!! + /// Returns a new Promise object (in case of error), or a result of "crypto.subtle.veryfy" function + + // #region Global variables + var _this = this; + var sha_algorithm = ""; + + var sequence = Promise.resolve(); + + var subjectPublicKeyInfo = this.subjectPublicKeyInfo; + var signature = this.signatureValue; + var tbs = this.tbs; + + var ecdsaKeySize = 0; + // #endregion + + // #region Get a "crypto" extension + var crypto = in_window.org.pkijs.getCrypto(); + if(typeof crypto == "undefined") + return Promise.reject("Unable to create WebCrypto object"); + // #endregion + + // #region Find a correct hashing algorithm + sha_algorithm = in_window.org.pkijs.getHashAlgorithm(this.signatureAlgorithm); + if(sha_algorithm === "") + return Promise.reject("Unsupported signature algorithm: " + _this.signatureAlgorithm.algorithm_id); + // #endregion + + // #region Importing public key + sequence = sequence.then( + function() + { + // #region Get information about public key algorithm and default parameters for import + var algorithmObject = in_window.org.pkijs.getAlgorithmByOID(_this.signatureAlgorithm.algorithm_id); + if(("name" in algorithmObject) === false) + return Promise.reject("Unsupported public key algorithm: " + _this.signatureAlgorithm.algorithm_id); + + var algorithm_name = algorithmObject.name; + + var algorithm = in_window.org.pkijs.getAlgorithmParameters(algorithm_name, "importkey"); + if("hash" in algorithm.algorithm) + algorithm.algorithm.hash.name = sha_algorithm; + + // #region Special case for ECDSA + if(algorithm_name === "ECDSA") + { + // #region Get information about named curve + if((subjectPublicKeyInfo.algorithm.algorithm_params instanceof in_window.org.pkijs.asn1.OID) === false) + return Promise.reject("Incorrect type for ECDSA public key parameters"); + + var curveObject = in_window.org.pkijs.getAlgorithmByOID(subjectPublicKeyInfo.algorithm.algorithm_params.value_block.toString()); + if(("name" in curveObject) === false) + return Promise.reject("Unsupported named curve algorithm: " + subjectPublicKeyInfo.algorithm.algorithm_params.value_block.toString()); + // #endregion + + algorithm.algorithm.namedCurve = curveObject.name; + } + // #endregion + // #endregion + + var publicKeyInfo_schema = subjectPublicKeyInfo.toSchema(); + var publicKeyInfo_buffer = publicKeyInfo_schema.toBER(false); + var publicKeyInfo_view = new Uint8Array(publicKeyInfo_buffer); + + return crypto.importKey("spki", publicKeyInfo_view, algorithm.algorithm, true, algorithm.usages); + } + ); + // #endregion + + // #region Verify signature + sequence = sequence.then( + function(publicKey) + { + // #region Get default algorithm parameters for verification + var algorithm = in_window.org.pkijs.getAlgorithmParameters(publicKey.algorithm.name, "verify"); + if("hash" in algorithm.algorithm) + algorithm.algorithm.hash.name = sha_algorithm; + // #endregion + + // #region Special case for ECDSA signatures + var signature_value = signature.value_block.value_hex; + + if(publicKey.algorithm.name === "ECDSA") + { + var asn1 = in_window.org.pkijs.fromBER(signature_value); + signature_value = in_window.org.pkijs.createECDSASignatureFromCMS(asn1.result); + } + // #endregion + + // #region Special case for RSA-PSS + if(publicKey.algorithm.name === "RSA-PSS") + { + var pssParameters; + + try + { + pssParameters = new in_window.org.pkijs.simpl.x509.RSASSA_PSS_params({ schema: _this.signatureAlgorithm.algorithm_params }); + } + catch(ex) + { + return Promise.reject(ex); + } + + if("saltLength" in pssParameters) + algorithm.algorithm.saltLength = pssParameters.saltLength; + else + algorithm.algorithm.saltLength = 20; + + var hash_algo = "SHA-1"; + + if("hashAlgorithm" in pssParameters) + { + var hashAlgorithm = in_window.org.pkijs.getAlgorithmByOID(pssParameters.hashAlgorithm.algorithm_id); + if(("name" in hashAlgorithm) === false) + return Promise.reject("Unrecognized hash algorithm: " + pssParameters.hashAlgorithm.algorithm_id); + + hash_algo = hashAlgorithm.name; + } + + algorithm.algorithm.hash.name = hash_algo; + } + // #endregion + + return crypto.verify(algorithm.algorithm, + publicKey, + new Uint8Array(signature_value), + new Uint8Array(tbs)); + } + ); + // #endregion + + return sequence; + }; + //************************************************************************************** + in_window.org.pkijs.simpl.PKCS10.prototype.sign = + function(privateKey, hashAlgorithm) + { + /// Private key for "subjectPublicKeyInfo" structure + /// Hashing algorithm. Default SHA-1 + + // #region Initial variables + var _this = this; + // #endregion + + // #region Get a private key from function parameter + if(typeof privateKey === "undefined") + return Promise.reject("Need to provide a private key for signing"); + // #endregion + + // #region Get hashing algorithm + if(typeof hashAlgorithm === "undefined") + hashAlgorithm = "SHA-1"; + else + { + // #region Simple check for supported algorithm + var oid = in_window.org.pkijs.getOIDByAlgorithm({ name: hashAlgorithm }); + if(oid === "") + return Promise.reject("Unsupported hash algorithm: " + hashAlgorithm); + // #endregion + } + // #endregion + + // #region Get a "default parameters" for current algorithm + var defParams = in_window.org.pkijs.getAlgorithmParameters(privateKey.algorithm.name, "sign"); + defParams.algorithm.hash.name = hashAlgorithm; + // #endregion + + // #region Fill internal structures base on "privateKey" and "hashAlgorithm" + switch(privateKey.algorithm.name.toUpperCase()) + { + case "RSASSA-PKCS1-V1_5": + case "ECDSA": + _this.signatureAlgorithm.algorithm_id = in_window.org.pkijs.getOIDByAlgorithm(defParams.algorithm); + break; + case "RSA-PSS": + { + // #region Set "saltLength" as a length (in octets) of hash function result + switch(hashAlgorithm.toUpperCase()) + { + case "SHA-256": + defParams.algorithm.saltLength = 32; + break; + case "SHA-384": + defParams.algorithm.saltLength = 48; + break; + case "SHA-512": + defParams.algorithm.saltLength = 64; + break; + default:; + } + // #endregion + + // #region Fill "RSASSA_PSS_params" object + var paramsObject = {}; + + if(hashAlgorithm.toUpperCase() !== "SHA-1") + { + var hashAlgorithmOID = in_window.org.pkijs.getOIDByAlgorithm({ name: hashAlgorithm }); + if(hashAlgorithmOID === "") + return Promise.reject("Unsupported hash algorithm: " + hashAlgorithm); + + paramsObject.hashAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: hashAlgorithmOID, + algorithm_params: new in_window.org.pkijs.asn1.NULL() + }); + + paramsObject.maskGenAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: "1.2.840.113549.1.1.8", // MGF1 + algorithm_params: paramsObject.hashAlgorithm.toSchema() + }) + } + + if(defParams.algorithm.saltLength !== 20) + paramsObject.saltLength = defParams.algorithm.saltLength; + + var pssParameters = new in_window.org.pkijs.simpl.x509.RSASSA_PSS_params(paramsObject); + // #endregion + + // #region Automatically set signature algorithm + _this.signatureAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ + algorithm_id: "1.2.840.113549.1.1.10", + algorithm_params: pssParameters.toSchema() + }); + // #endregion + } + break; + default: + return Promise.reject("Unsupported signature algorithm: " + privateKey.algorithm.name); + } + // #endregion + + // #region Create TBS data for signing + _this.tbs = in_window.org.pkijs.simpl.PKCS10.prototype.encodeTBS.call(this).toBER(false); + // #endregion + + // #region Get a "crypto" extension + var crypto = in_window.org.pkijs.getCrypto(); + if(typeof crypto == "undefined") + return Promise.reject("Unable to create WebCrypto object"); + // #endregion + + // #region Signing TBS data on provided private key + return crypto.sign(defParams.algorithm, + privateKey, + new Uint8Array(_this.tbs)).then( + function(result) + { + // #region Special case for ECDSA algorithm + if(defParams.algorithm.name === "ECDSA") + result = in_window.org.pkijs.createCMSECDSASignature(result); + // #endregion + + _this.signatureValue = new in_window.org.pkijs.asn1.BITSTRING({ value_hex: result }); + }, + function(error) + { + return Promise.reject("Signing error: " + error); + } + ); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.PKCS10.prototype.toJSON = + function() + { + var _object = { + tbs: in_window.org.pkijs.bufferToHexCodes(this.tbs, 0, this.tbs.byteLength), + version: this.version, + subject: this.subject.toJSON(), + subjectPublicKeyInfo: this.subjectPublicKeyInfo.toJSON(), + signatureAlgorithm: this.signatureAlgorithm.toJSON(), + signatureValue: this.signatureValue.toJSON() + }; + + if("attributes" in this) + { + _object.attributes = new Array(); + + for(var i = 0; i < this.attributes.length; i++) + _object.attributes.push(this.attributes[i].toJSON()); + } + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for PKCS#8 private key bag + //************************************************************************************** + in_window.org.pkijs.simpl.PKCS8 = + function() + { + // #region Internal properties of the object + this.version = 0; + this.privateKeyAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.privateKey = new in_window.org.pkijs.asn1.OCTETSTRING(); + // OPTIONAL this.attributes // Array of "in_window.org.pkijs.simpl.ATTRIBUTE" + // #endregion + + // #region If input argument array contains "schema" for this object + if((arguments[0] instanceof Object) && ("schema" in arguments[0])) + in_window.org.pkijs.simpl.PKCS8.prototype.fromSchema.call(this, arguments[0].schema); + // #endregion + // #region If input argument array contains "native" values for internal properties + else + { + if(arguments[0] instanceof Object) + { + this.version = arguments[0].version || 0; + this.privateKeyAlgorithm = arguments[0].privateKeyAlgorithm || new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER(); + this.privateKey = arguments[0].privateKey || new in_window.org.pkijs.asn1.OCTETSTRING(); + + if("attributes" in arguments[0]) + this.attributes = arguments[0].attributes; + } + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.PKCS8.prototype.fromSchema = + function(schema) + { + // #region Check the schema is valid + var asn1 = in_window.org.pkijs.compareSchema(schema, + schema, + in_window.org.pkijs.schema.PKCS8({ + names: { + version: "version", + privateKeyAlgorithm: { + names: { + block_name: "privateKeyAlgorithm" + } + }, + privateKey: "privateKey", + attributes: "attributes" + } + }) + ); + + if(asn1.verified === false) + throw new Error("Object's schema was not verified against input data for PKCS8"); + // #endregion + + // #region Get internal properties from parsed schema + this.version = asn1.result["version"].value_block.value_dec; + this.privateKeyAlgorithm = new in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER({ schema: asn1.result["privateKeyAlgorithm"] }); + this.privateKey = asn1.result["privateKey"]; + + if("attributes" in asn1.result) + { + this.attributes = new Array(); + var attrs = asn1.result["attributes"]; + + for(var i = 0; i < attrs.length; i++) + this.attributes.push(new in_window.org.pkijs.simpl.ATTRIBUTE({ schema: attrs[i] })); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.PKCS8.prototype.toSchema = + function() + { + // #region Create array for output sequence + var output_array = new Array(); + + output_array.push(new in_window.org.pkijs.asn1.INTEGER({ value: this.version })); + output_array.push(this.privateKeyAlgorithm.toSchema()); + output_array.push(this.privateKey); + + if("attributes" in this) + { + var attrs = new Array(); + + for(var i = 0; i < this.attributes.length; i++) + attrs.push(this.attributes[i].toSchema()); + + output_array.push(new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({ + optional: true, + id_block: { + tag_class: 3, // CONTEXT-SPECIFIC + tag_number: 0 // [0] + }, + value: attrs + })); + } + // #endregion + + // #region Construct and return new ASN.1 schema for this object + return (new in_window.org.pkijs.asn1.SEQUENCE({ + value: output_array + })); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.PKCS8.prototype.toJSON = + function() + { + var _object = { + version: this.version, + privateKeyAlgorithm: this.privateKeyAlgorithm.toJSON(), + privateKey: this.privateKey.toJSON() + }; + + if("attributes" in this) + { + _object.attributes = new Array(); + + for(var i = 0; i < this.attributes.length; i++) + _object.attributes.push(this.attributes[i].toJSON()); + } + + return _object; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** + // #region Simplified structure for working with X.509 certificate chains + //************************************************************************************** + in_window.org.pkijs.simpl.CERT_CHAIN = + function() + { + // #region Internal properties of the object + /// Array of pre-defined trusted (by user) certificates + this.trusted_certs = new Array(); + /// Array with certificate chain. Could be only one end-user certificate in there! + this.certs = new Array(); + /// Array of all CRLs for all certificates from certificate chain + this.crls = new Array(); + // #endregion + + // #region Initialize internal properties by input values + if(arguments[0] instanceof Object) + { + this.trusted_certs = arguments[0].trusted_certs || new Array(); + this.certs = arguments[0].certs || new Array(); + this.crls = arguments[0].crls || new Array(); + } + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CERT_CHAIN.prototype.sort = + function() + { + // #region Initial variables + /// Array of sorted certificates + var sorted_certs = new Array(); + + /// Initial array of certificates + var certs = this.certs.slice(0); // Explicity copy "this.certs" + + /// Date for checking certificate validity period + var check_date = new Date(); + + var _this = this; + // #endregion + + // #region Initial checks + if(certs.length === 0) + return new Promise(function(resolve, reject) + { + reject({ + result: false, + result_code: 2, + result_message: "Certificate's array can not be empty" + }); + }); + // #endregion + + // #region Find end-user certificate + var end_user_index = -1; + + for(var i = 0; i < certs.length; i++) + { + var isCA = false; + + if("extensions" in certs[i]) + { + var mustBeCA = false; + var keyUsagePresent = false; + var cRLSign = false; + + for(var j = 0; j < certs[i].extensions.length; j++) + { + if((certs[i].extensions[j].critical === true) && + (("parsedValue" in certs[i].extensions[j]) === false)) + { + return new Promise(function(resolve, reject) + { + reject({ + result: false, + result_code: 6, + result_message: "Unable to parse critical certificate extension: " + certs[i].extensions[j].extnID + }); + }); + } + + if(certs[i].extensions[j].extnID === "2.5.29.15") // KeyUsage + { + keyUsagePresent = true; + + var view = new Uint8Array(certs[i].extensions[j].parsedValue.value_block.value_hex); + + if((view[0] & 0x04) === 0x04) // Set flag "keyCertSign" + mustBeCA = true; + + if((view[0] & 0x02) === 0x02) // Set flag "cRLSign" + cRLSign = true; + } + + if(certs[i].extensions[j].extnID === "2.5.29.19") // BasicConstraints + { + if("cA" in certs[i].extensions[j].parsedValue) + { + if(certs[i].extensions[j].parsedValue.cA === true) + isCA = true; + } + } + } + + if((mustBeCA === true) && (isCA === false)) + return new Promise(function(resolve, reject) + { + reject({ + result: false, + result_code: 3, + result_message: "Unable to build certificate chain - using \"keyCertSign\" flag set without BasicConstaints" + }); + }); + + if((keyUsagePresent === true) && (isCA === true) && (mustBeCA === false)) + return new Promise(function(resolve, reject) + { + reject({ + result: false, + result_code: 4, + result_message: "Unable to build certificate chain - \"keyCertSign\" flag was not set" + }); + }); + + if((isCA === true) && (keyUsagePresent === true) && (cRLSign === false)) + return new Promise(function(resolve, reject) + { + reject({ + result: false, + result_code: 5, + result_message: "Unable to build certificate chain - intermediate certificate must have \"cRLSign\" key usage flag" + }); + }); + } + + if(isCA === false) + { + if(sorted_certs.length !== 0) + return new Promise(function(resolve, reject) + { + reject({ + result: false, + result_code: 7, + result_message: "Unable to build certificate chain - more than one possible end-user certificate" + }); + }); + + sorted_certs.push(certs[i]); + end_user_index = i; + } + } + + certs.splice(end_user_index, 1); + // #endregion + + // #region Check that end-user certificate was found + if(sorted_certs.length === 0) + return new Promise(function(resolve, reject) + { + reject({ + result: false, + result_code: 1, + result_message: "Can't find end-user certificate" + }); + }); + // #endregion + + // #region Return if there is only one certificate in certificate's array + if(certs.length === 0) + { + if(sorted_certs[0].issuer.isEqual(sorted_certs[0].subject) === true) + return new Promise(function(resolve, reject) { resolve(sorted_certs); }); + else + { + if(this.trusted_certs.length === 0) + { + return new Promise(function(resolve, reject) + { + reject({ + result: false, + result_code: 70, + result_message: "Can't find root certificate" + }); + }); + } + else + { + certs = _this.trusted_certs.splice(0); + } + } + + } + // #endregion + + /// Current certificate (to find issuer for) + var current_certificate = sorted_certs[0]; + + // #region Auxiliary functions working with Promises + function basic(subject_certificate, issuer_certificate) + { + /// Basic certificate checks + /// Certificate for testing (subject) + /// Certificate for issuer of subject certificate + + // #region Initial variables + var sequence = Promise.resolve(); + // #endregion + + // #region Check validity period for subject certificate + sequence = sequence.then( + function() + { + if((subject_certificate.notBefore.value > check_date) || + (subject_certificate.notAfter.value < check_date)) + { + return new Promise(function(resolve, reject) + { + reject({ + result: false, + result_code: 8, + result_message: "Certificate validity period is out of checking date" + }); + }); + } + } + ); + // #endregion + + // #region Give ability to not provide CRLs (all certificates assume to be valid) + if(_this.crls.length === 0) + return sequence.then( + function() + { + return new Promise(function(resolve, reject) { resolve(); }); + } + ); + // #endregion + + // #region Find correct CRL for "issuer_certificate" + function find_crl(index) + { + return _this.crls[index].verify({ issuerCertificate: issuer_certificate }).then( + function(result) + { + if(result === true) + return new Promise(function(resolve, reject) { resolve(_this.crls[index]); }); + else + { + index++; + + if(index < _this.crls.length) + return find_crl(index); + else + return new Promise(function(resolve, reject) + { + reject({ + result: false, + result_code: 9, + result_message: "Unable to find CRL for issuer's certificate" + }); + }); + } + }, + function(error) + { + return new Promise(function(resolve, reject) + { + reject({ + result: false, + result_code: 10, + result_message: "Unable to find CRL for issuer's certificate" + }); + }); + } + ); + } + + sequence = sequence.then( + function() + { + return find_crl(0); + } + ); + // #endregion + + // #region Check that subject certificate is not in the CRL + sequence = sequence.then( + function(crl) + { + /// CRL for issuer's certificate + + if(crl.isCertificateRevoked({ certificate: subject_certificate }) === true) + return new Promise(function(resolve, reject) + { + reject({ + result: false, + result_code: 11, + result_message: "Subject certificate was revoked" + }); + }); + else + return new Promise(function(resolve, reject) { resolve(); }); + }, + function(error) + { + /// Not for all certificates we have a CRL. So, this "stub" is for handling such situation - assiming we have a valid, non-revoked certificate + return new Promise(function(resolve, reject) { resolve(); }); + } + ); + // #endregion + + return sequence; + } + + function outer() + { + return inner(current_certificate, 0).then( + function(index) + { + sorted_certs.push(certs[index]); + current_certificate = certs[index]; + + certs.splice(index, 1); + + if(current_certificate.issuer.isEqual(current_certificate.subject) === true) + { + // #region Check that the "self-signed" certificate there is in "trusted_certs" array + var found = (_this.trusted_certs.length === 0); // If user did not set "trusted_certs" then we have an option to trust any self-signed certificate as root + + for(var i = 0; i < _this.trusted_certs.length; i++) + { + if((current_certificate.issuer.isEqual(_this.trusted_certs[i].issuer) === true) && + (current_certificate.subject.isEqual(_this.trusted_certs[i].subject) === true) && + (current_certificate.serialNumber.isEqual(_this.trusted_certs[i].serialNumber) === true)) + { + found = true; + break; + } + } + + if(found === false) + return new Promise(function(resolve, reject) + { + reject({ + result: false, + result_code: 22, + result_message: "Self-signed root certificate not in \"trusted certificates\" array" + }); + }); + // #endregion + + return (current_certificate.verify()).then( // Verifing last, self-signed certificate + function(result) + { + if(result === true) + return basic(current_certificate, current_certificate).then( + function() + { + return new Promise(function(resolve, reject) { resolve(sorted_certs); }); + }, + function(error) + { + return new Promise(function(resolve, reject) + { + reject({ + result: false, + result_code: 12, + result_message: error + }); + }); + } + ); + else + return new Promise(function(resolve, reject) + { + reject({ + result: false, + result_code: 13, + result_message: "Unable to build certificate chain - signature of root certificate is invalid" + }); + }); + }, + function(error) + { + return new Promise(function(resolve, reject) + { + reject({ + result: false, + result_code: 14, + result_message: error + }); + }); + } + ); + } + else // In case if self-signed cert for the chain in the "trusted_certs" array + { + if(certs.length > 0) + return outer(); + else + { + if(_this.trusted_certs.length !== 0) + { + certs = _this.trusted_certs.splice(0); + return outer(); + } + else + return new Promise(function(resolve, reject) + { + reject({ + result: false, + result_code: 23, + result_message: "Root certificate not found" + }); + }); + } + } + }, + function(error) + { + return new Promise(function(resolve, reject) + { + reject(error); + }); + } + ); + } + + function inner(current_certificate, index) + { + if(certs[index].subject.isEqual(current_certificate.issuer) === true) + { + return current_certificate.verify({ issuerCertificate: certs[index] }).then( + function(result) + { + if(result === true) + { + return basic(current_certificate, certs[index]).then( + function() + { + return new Promise(function(resolve, reject) { resolve(index); }); + }, + function(error) + { + return new Promise(function(resolve, reject) + { + reject({ + result: false, + result_code: 16, + result_message: error + }); + }); + } + ); + } + else + { + if(index < (certs.length - 1)) + return inner(current_certificate, index + 1); + else + return new Promise(function(resolve, reject) + { + reject({ + result: false, + result_code: 17, + result_message: "Unable to build certificate chain - incomplete certificate chain or signature of some certificate is invalid" + }); + }); + } + }, + function(error) + { + return new Promise(function(resolve, reject) + { + reject({ + result: false, + result_code: 18, + result_message: "Unable to build certificate chain - error during certificate signature verification" + }); + }); + } + ); + } + else + { + if(index < (certs.length - 1)) + return inner(current_certificate, index + 1); + else + return new Promise(function(resolve, reject) + { + reject({ + result: false, + result_code: 19, + result_message: "Unable to build certificate chain - incomplete certificate chain" + }); + }); + } + } + // #endregion + + // #region Find certificates for all issuers + return outer(); + // #endregion + }; + //************************************************************************************** + in_window.org.pkijs.simpl.CERT_CHAIN.prototype.verify = + function() + { + // #region Initial checks + if(this.certs.length === 0) + return new Promise(function(resolve, reject) { reject("Empty certificate array"); }); + // #endregion + + // #region Initial variables + var sequence = Promise.resolve(); + + var _this = this; + // #endregion + + // #region Get input variables + var initial_policy_set = new Array(); + initial_policy_set.push("2.5.29.32.0"); // "anyPolicy" + + var initial_explicit_policy = false; + var initial_policy_mapping_inhibit = false; + var initial_inhibit_policy = false; + + var initial_permitted_subtrees_set = new Array(); // Array of "simpl.x509.GeneralSubtree" + var initial_excluded_subtrees_set = new Array(); // Array of "simpl.x509.GeneralSubtree" + var initial_required_name_forms = new Array(); // Array of "simpl.x509.GeneralSubtree" + + var verification_time = new Date(); + + if(arguments[0] instanceof Object) + { + if("initial_policy_set" in arguments[0]) + initial_policy_set = arguments[0].initial_policy_set; + + if("initial_explicit_policy" in arguments[0]) + initial_explicit_policy = arguments[0].initial_explicit_policy; + + if("initial_policy_mapping_inhibit" in arguments[0]) + initial_policy_mapping_inhibit = arguments[0].initial_policy_mapping_inhibit; + + if("initial_inhibit_policy" in arguments[0]) + initial_inhibit_policy = arguments[0].initial_inhibit_policy; + + if("initial_permitted_subtrees_set" in arguments[0]) + initial_permitted_subtrees_set = arguments[0].initial_permitted_subtrees_set; + + if("initial_excluded_subtrees_set" in arguments[0]) + initial_excluded_subtrees_set = arguments[0].initial_excluded_subtrees_set; + + if("initial_required_name_forms" in arguments[0]) + initial_required_name_forms = arguments[0].initial_required_name_forms; + } + + var explicit_policy_indicator = initial_explicit_policy; + var policy_mapping_inhibit_indicator = initial_policy_mapping_inhibit; + var inhibit_any_policy_indicator = initial_inhibit_policy; + + var pending_constraints = new Array(3); + pending_constraints[0] = false; // For "explicit_policy_pending" + pending_constraints[1] = false; // For "policy_mapping_inhibit_pending" + pending_constraints[2] = false; // For "inhibit_any_policy_pending" + + var explicit_policy_pending = 0; + var policy_mapping_inhibit_pending = 0; + var inhibit_any_policy_pending = 0; + + var permitted_subtrees = initial_permitted_subtrees_set; + var excluded_subtrees = initial_excluded_subtrees_set; + var required_name_forms = initial_required_name_forms; + + var path_depth = 1; + // #endregion + + // #region Sorting certificates in the chain array + sequence = (in_window.org.pkijs.simpl.CERT_CHAIN.prototype.sort.call(this)).then( + function(sorted_certs) + { + _this.certs = sorted_certs; + } + ); + // #endregion + + // #region Work with policies + sequence = sequence.then( + function() + { + // #region Support variables + var all_policies = new Array(); // Array of all policies (string values) + all_policies.push("2.5.29.32.0"); // Put "anyPolicy" at first place + + var policies_and_certs = new Array(); // In fact "array of array" where rows are for each specific policy, column for each certificate and value is "true/false" + + var any_policy_array = new Array(_this.certs.length - 1); // Minus "trusted anchor" + for(var ii = 0; ii < (_this.certs.length - 1) ; ii++) + any_policy_array[ii] = true; + + policies_and_certs.push(any_policy_array); + + var policy_mappings = new Array(_this.certs.length - 1); // Array of "PolicyMappings" for each certificate + var cert_policies = new Array(_this.certs.length - 1); // Array of "CertificatePolicies" for each certificate + // #endregion + + for(var i = (_this.certs.length - 2) ; i >= 0 ; i--, path_depth++) + { + if("extensions" in _this.certs[i]) + { + for(var j = 0; j < _this.certs[i].extensions.length; j++) + { + // #region CertificatePolicies + if(_this.certs[i].extensions[j].extnID === "2.5.29.32") + { + cert_policies[i] = _this.certs[i].extensions[j].parsedValue; + + for(var k = 0; k < _this.certs[i].extensions[j].parsedValue.certificatePolicies.length; k++) + { + var policy_index = (-1); + + // #region Try to find extension in "all_policies" array + for(var s = 0; s < all_policies.length; s++) + { + if(_this.certs[i].extensions[j].parsedValue.certificatePolicies[k].policyIdentifier === all_policies[s]) + { + policy_index = s; + break; + } + } + // #endregion + + if(policy_index === (-1)) + { + all_policies.push(_this.certs[i].extensions[j].parsedValue.certificatePolicies[k].policyIdentifier); + + var cert_array = new Array(_this.certs.length - 1); + cert_array[i] = true; + + policies_and_certs.push(cert_array); + } + else(policies_and_certs[policy_index])[i] = true; + } + } + // #endregion + + // #region PolicyMappings + if(_this.certs[i].extensions[j].extnID === "2.5.29.33") + policy_mappings[i] = _this.certs[i].extensions[j].parsedValue; + // #endregion + + // #region PolicyConstraints + if(_this.certs[i].extensions[j].extnID === "2.5.29.36") + { + if(explicit_policy_indicator == false) + { + // #region requireExplicitPolicy + if(_this.certs[i].extensions[j].parsedValue.requireExplicitPolicy === 0) + explicit_policy_indicator = true; + else + { + if(pending_constraints[0] === false) + { + pending_constraints[0] = true; + explicit_policy_pending = _this.certs[i].extensions[j].parsedValue.requireExplicitPolicy; + } + else + { + explicit_policy_pending = (explicit_policy_pending > _this.certs[i].extensions[j].parsedValue.requireExplicitPolicy) ? _this.certs[i].extensions[j].parsedValue.requireExplicitPolicy : explicit_policy_pending; + } + } + // #endregion + + // #region inhibitPolicyMapping + if(_this.certs[i].extensions[j].parsedValue.inhibitPolicyMapping === 0) + policy_mapping_inhibit_indicator = true; + else + { + if(pending_constraints[1] === false) + { + pending_constraints[1] = true; + policy_mapping_inhibit_pending = _this.certs[i].extensions[j].parsedValue.requireExplicitPolicy; + } + else + { + policy_mapping_inhibit_pending = (policy_mapping_inhibit_pending > _this.certs[i].extensions[j].parsedValue.requireExplicitPolicy) ? _this.certs[i].extensions[j].parsedValue.requireExplicitPolicy : policy_mapping_inhibit_pending; + } + } + // #endregion + } + } + // #endregion + + // #region InhibitAnyPolicy + if(_this.certs[i].extensions[j].extnID === "2.5.29.54") + { + if(inhibit_any_policy_indicator === false) + { + if(_this.certs[i].extensions[j].parsedValue.value_block.value_dec === 0) + inhibit_any_policy_indicator = true; + else + { + if(pending_constraints[2] === false) + { + pending_constraints[2] = true; + inhibit_any_policy_pending = _this.certs[i].extensions[j].parsedValue.value_block.value_dec; + } + else + { + inhibit_any_policy_pending = (inhibit_any_policy_pending > _this.certs[i].extensions[j].parsedValue.value_block.value_dec) ? _this.certs[i].extensions[j].parsedValue.value_block.value_dec : inhibit_any_policy_pending; + } + } + } + } + // #endregion + } + + // #region Check "inhibit_any_policy_indicator" + if(inhibit_any_policy_indicator === true) + delete (policies_and_certs[0])[i]; // Unset value to "undefined" for "anyPolicies" value for current certificate + // #endregion + + // #region Combine information from certificate policies and policy mappings + if((typeof cert_policies[i] !== "undefined") && + (typeof policy_mappings[i] !== "undefined") && + (policy_mapping_inhibit_indicator === false)) + { + for(var m = 0; m < cert_policies[i].certificatePolicies.length; m++) + { + var domainPolicy = ""; + + // #region Find if current policy is in "mappings" array + for(var n = 0; n < policy_mappings[i].mappings.length; n++) + { + if(policy_mappings[i].mappings[n].subjectDomainPolicy === cert_policies[i].certificatePolicies[m].policyIdentifier) + { + domainPolicy = policy_mappings[i].mappings[n].issuerDomainPolicy; + break; + } + + // #region Could be the case for some reasons + if(policy_mappings[i].mappings[n].issuerDomainPolicy === cert_policies[i].certificatePolicies[m].policyIdentifier) + { + domainPolicy = policy_mappings[i].mappings[n].subjectDomainPolicy; + break; + } + // #endregion + } + + if(domainPolicy === "") + continue; + // #endregion + + // #region Find the index of "domainPolicy" + var domainPolicy_index = (-1); + + for(var p = 0; p < all_policies.length; p++) + { + if(all_policies[p] === domainPolicy) + { + domainPolicy_index = p; + break; + } + } + // #endregion + + // #region Change array value for "domainPolicy" + if(domainPolicy_index !== (-1)) + (policies_and_certs[domainPolicy_index])[i] = true; // Put "set" in "domainPolicy" cell for specific certificate + // #endregion + } + } + // #endregion + + // #region Process with "pending constraints" + if(explicit_policy_indicator === false) + { + if(pending_constraints[0] === true) + { + explicit_policy_pending--; + if(explicit_policy_pending === 0) + { + explicit_policy_indicator = true; + pending_constraints[0] = false; + } + } + } + + if(policy_mapping_inhibit_indicator === false) + { + if(pending_constraints[1] === true) + { + policy_mapping_inhibit_pending--; + if(policy_mapping_inhibit_pending === 0) + { + policy_mapping_inhibit_indicator = true; + pending_constraints[1] = false; + } + } + } + + if(inhibit_any_policy_indicator === false) + { + if(pending_constraints[2] === true) + { + inhibit_any_policy_pending--; + if(inhibit_any_policy_pending === 0) + { + inhibit_any_policy_indicator = true; + pending_constraints[2] = false; + } + } + } + // #endregion + } + } + + // #region Create "set of authorities-constrained policies" + var auth_constr_policies = new Array(); + + for(var i = 0; i < policies_and_certs.length; i++) + { + var found = true; + + for(var j = 0; j < (_this.certs.length - 1) ; j++) + { + if(typeof (policies_and_certs[i])[j] === "undefined") + { + found = false; + break; + } + } + + if(found === true) + auth_constr_policies.push(all_policies[i]); + } + // #endregion + + // #region Create "set of user-constrained policies" + var user_constr_policies = new Array(); + + for(var i = 0; i < auth_constr_policies.length; i++) + { + for(var j = 0; j < initial_policy_set.length; j++) + { + if(initial_policy_set[j] === auth_constr_policies[i]) + { + user_constr_policies.push(initial_policy_set[j]); + break; + } + } + } + // #endregion + + // #region Combine output object + return { + result: (user_constr_policies.length > 0), + result_code: 0, + result_message: (user_constr_policies.length > 0) ? "" : "Zero \"user_constr_policies\" array, no intersections with \"auth_constr_policies\"", + auth_constr_policies: auth_constr_policies, + user_constr_policies: user_constr_policies, + explicit_policy_indicator: explicit_policy_indicator, + policy_mappings: policy_mappings + }; + // #endregion + } + ); + // #endregion + + // #region Work with name constraints + sequence = sequence.then( + function(policy_result) + { + // #region Auxiliary functions for name constraints checking + function compare_dNSName(name, constraint) + { + /// Compare two dNSName values + /// DNS from name + /// Constraint for DNS from name + /// Boolean result - valid or invalid the "name" against the "constraint" + + // #region Make a "string preparation" for both name and constrain + var name_prepared = in_window.org.pkijs.stringPrep(name); + var constraint_prepared = in_window.org.pkijs.stringPrep(constraint); + // #endregion + + // #region Make a "splitted" versions of "constraint" and "name" + var name_splitted = name_prepared.split("."); + var constraint_splitted = constraint_prepared.split("."); + // #endregion + + // #region Length calculation and additional check + var name_len = name_splitted.length; + var constr_len = constraint_splitted.length; + + if((name_len === 0) || (constr_len === 0) || (name_len < constr_len)) + return false; + // #endregion + + // #region Check that no part of "name" has zero length + for(var i = 0; i < name_len; i++) + { + if(name_splitted[i].length === 0) + return false; + } + // #endregion + + // #region Check that no part of "constraint" has zero length + for(var i = 0; i < constr_len; i++) + { + if(constraint_splitted[i].length === 0) + { + if(i === 0) + { + if(constr_len === 1) + return false; + else + continue; + } + + return false; + } + } + // #endregion + + // #region Check that "name" has a tail as "constraint" + + for(var i = 0; i < constr_len; i++) + { + if(constraint_splitted[constr_len - 1 - i].length === 0) + continue; + + if(name_splitted[name_len - 1 - i].localeCompare(constraint_splitted[constr_len - 1 - i]) !== 0) + return false; + } + // #endregion + + return true; + } + + function compare_rfc822Name(name, constraint) + { + /// Compare two rfc822Name values + /// E-mail address from name + /// Constraint for e-mail address from name + /// Boolean result - valid or invalid the "name" against the "constraint" + + // #region Make a "string preparation" for both name and constrain + var name_prepared = in_window.org.pkijs.stringPrep(name); + var constraint_prepared = in_window.org.pkijs.stringPrep(constraint); + // #endregion + + // #region Make a "splitted" versions of "constraint" and "name" + var name_splitted = name_prepared.split("@"); + var constraint_splitted = constraint_prepared.split("@"); + // #endregion + + // #region Splitted array length checking + if((name_splitted.length === 0) || (constraint_splitted.length === 0) || (name_splitted.length < constraint_splitted.length)) + return false; + // #endregion + + if(constraint_splitted.length === 1) + { + var result = compare_dNSName(name_splitted[1], constraint_splitted[0]); + + if(result) + { + // #region Make a "splitted" versions of domain name from "constraint" and "name" + var ns = name_splitted[1].split("."); + var cs = constraint_splitted[0].split("."); + // #endregion + + if(cs[0].length === 0) + return true; + + return ns.length === cs.length; + } + else + return false; + } + else + return (name_prepared.localeCompare(constraint_prepared) === 0); + + return false; + } + + function compare_uniformResourceIdentifier(name, constraint) + { + /// Compare two uniformResourceIdentifier values + /// uniformResourceIdentifier from name + /// Constraint for uniformResourceIdentifier from name + /// Boolean result - valid or invalid the "name" against the "constraint" + + // #region Make a "string preparation" for both name and constrain + var name_prepared = in_window.org.pkijs.stringPrep(name); + var constraint_prepared = in_window.org.pkijs.stringPrep(constraint); + // #endregion + + // #region Find out a major URI part to compare with + var ns = name_prepared.split("/"); + var cs = constraint_prepared.split("/"); + + if(cs.length > 1) // Malformed constraint + return false; + + if(ns.length > 1) // Full URI string + { + for(var i = 0; i < ns.length; i++) + { + if((ns[i].length > 0) && (ns[i].charAt(ns[i].length - 1) !== ':')) + { + var ns_port = ns[i].split(":"); + name_prepared = ns_port[0]; + break; + } + } + } + // #endregion + + var result = compare_dNSName(name_prepared, constraint_prepared); + + if(result) + { + // #region Make a "splitted" versions of "constraint" and "name" + var name_splitted = name_prepared.split("."); + var constraint_splitted = constraint_prepared.split("."); + // #endregion + + if(constraint_splitted[0].length === 0) + return true; + + return name_splitted.length === constraint_splitted.length; + } + else + return false; + + return false; + } + + function compare_iPAddress(name, constraint) + { + /// Compare two iPAddress values + /// iPAddress from name + /// Constraint for iPAddress from name + /// Boolean result - valid or invalid the "name" against the "constraint" + + // #region Common variables + var name_view = new Uint8Array(name.value_block.value_hex); + var constraint_view = new Uint8Array(constraint.value_block.value_hex); + // #endregion + + // #region Work with IPv4 addresses + if((name_view.length === 4) && (constraint_view.length === 8)) + { + for(var i = 0; i < 4; i++) + { + if((name_view[i] ^ constraint_view[i]) & constraint_view[i + 4]) + return false; + } + + return true; + } + // #endregion + + // #region Work with IPv6 addresses + if((name_view.length === 16) && (constraint_view.length === 32)) + { + for(var i = 0; i < 16; i++) + { + if((name_view[i] ^ constraint_view[i]) & constraint_view[i + 16]) + return false; + } + + return true; + } + // #endregion + + return false; + } + + function compare_directoryName(name, constraint) + { + /// Compare two directoryName values + /// directoryName from name + /// Constraint for directoryName from name + /// Boolean flag - should be comparision interrupted after first match or we need to match all "constraints" parts + /// Boolean result - valid or invalid the "name" against the "constraint" + + // #region Initial check + if((name.types_and_values.length === 0) || (constraint.types_and_values.length === 0)) + return true; + + if(name.types_and_values.length < constraint.types_and_values.length) + return false; + // #endregion + + // #region Initial variables + var result = true; + var name_start = 0; + // #endregion + + for(var i = 0; i < constraint.types_and_values.length; i++) + { + var local_result = false; + + for(var j = name_start; j < name.types_and_values.length; j++) + { + local_result = name.types_and_values[j].isEqual(constraint.types_and_values[i]); + + if(name.types_and_values[j].type === constraint.types_and_values[i].type) + result = result && local_result; + + if(local_result === true) + { + if((name_start === 0) || (name_start === j)) + { + name_start = j + 1; + break; + } + else // Structure of "name" must be the same with "constraint" + return false; + } + } + + if(local_result === false) + return false; + } + + return (name_start === 0) ? false : result; + } + // #endregion + + // #region Check a result from "policy checking" part + if(policy_result.result === false) + return policy_result; + // #endregion + + // #region Check all certificates, excluding "trust anchor" + path_depth = 1; + + for(var i = (_this.certs.length - 2) ; i >= 0 ; i--, path_depth++) + { + // #region Support variables + var subject_alt_names = new Array(); + + var cert_permitted_subtrees = new Array(); + var cert_excluded_subtrees = new Array(); + // #endregion + + if("extensions" in _this.certs[i]) + { + for(var j = 0; j < _this.certs[i].extensions.length; j++) + { + // #region NameConstraints + if(_this.certs[i].extensions[j].extnID === "2.5.29.30") + { + if("permittedSubtrees" in _this.certs[i].extensions[j].parsedValue) + cert_permitted_subtrees = cert_permitted_subtrees.concat(_this.certs[i].extensions[j].parsedValue.permittedSubtrees); + + if("excludedSubtrees" in _this.certs[i].extensions[j].parsedValue) + cert_excluded_subtrees = cert_excluded_subtrees.concat(_this.certs[i].extensions[j].parsedValue.excludedSubtrees); + } + // #endregion + + // #region SubjectAltName + if(_this.certs[i].extensions[j].extnID === "2.5.29.17") + subject_alt_names = subject_alt_names.concat(_this.certs[i].extensions[j].parsedValue.altNames); + // #endregion + } + } + + // #region Checking for "required name forms" + var form_found = (required_name_forms.length <= 0); + + for(var j = 0; j < required_name_forms.length; j++) + { + switch(required_name_forms[j].base.NameType) + { + case 4: // directoryName + { + if(required_name_forms[j].base.Name.types_and_values.length !== _this.certs[i].subject.types_and_values.length) + continue; + + form_found = true; + + for(var k = 0; k < _this.certs[i].subject.types_and_values.length; k++) + { + if(_this.certs[i].subject.types_and_values[k].type !== required_name_forms[j].base.Name.types_and_values[k].type) + { + form_found = false; + break; + } + } + + if(form_found === true) + break; + } + break; + default: // ??? Probably here we should reject the certificate ??? + } + } + + if(form_found === false) + { + policy_result.result = false; + policy_result.result_code = 21; + policy_result.result_message = "No neccessary name form found"; + + return new Promise(function(resolve, reject) + { + reject(policy_result); + }); + } + // #endregion + + // #region Checking for "permited sub-trees" + // #region Make groups for all types of constraints + var constr_groups = new Array(); // Array of array for groupped constraints + constr_groups[0] = new Array(); // rfc822Name + constr_groups[1] = new Array(); // dNSName + constr_groups[2] = new Array(); // directoryName + constr_groups[3] = new Array(); // uniformResourceIdentifier + constr_groups[4] = new Array(); // iPAddress + + for(var j = 0; j < permitted_subtrees.length; j++) + { + switch(permitted_subtrees[j].base.NameType) + { + // #region rfc822Name + case 1: + constr_groups[0].push(permitted_subtrees[j]); + break; + // #endregion + // #region dNSName + case 2: + constr_groups[1].push(permitted_subtrees[j]); + break; + // #endregion + // #region directoryName + case 4: + constr_groups[2].push(permitted_subtrees[j]); + break; + // #endregion + // #region uniformResourceIdentifier + case 6: + constr_groups[3].push(permitted_subtrees[j]); + break; + // #endregion + // #region iPAddress + case 7: + constr_groups[4].push(permitted_subtrees[j]); + break; + // #endregion + // #region default + + default: + // #endregion + } + } + // #endregion + + // #region Check name constraints groupped by type, one-by-one + for(var p = 0; p < 5; p++) + { + var group_permitted = false; + var valueExists = false; + var group = constr_groups[p]; + + for(var j = 0; j < group.length; j++) + { + switch(p) + { + // #region rfc822Name + case 0: + if(subject_alt_names.length > 0) + { + for(var k = 0; k < subject_alt_names.length; k++) + { + if(subject_alt_names[k].NameType === 1) // rfc822Name + { + valueExists = true; + group_permitted = group_permitted || compare_rfc822Name(subject_alt_names[k].Name, group[j].base.Name); + } + } + } + else // Try to find out "emailAddress" inside "subject" + { + for(var k = 0; k < _this.certs[i].subject.types_and_values.length; k++) + { + if((_this.certs[i].subject.types_and_values[k].type === "1.2.840.113549.1.9.1") || // PKCS#9 e-mail address + (_this.certs[i].subject.types_and_values[k].type === "0.9.2342.19200300.100.1.3")) // RFC1274 "rfc822Mailbox" e-mail address + { + valueExists = true; + group_permitted = group_permitted || compare_rfc822Name(_this.certs[i].subject.types_and_values[k].value.value_block.value, group[j].base.Name); + } + } + } + break; + // #endregion + // #region dNSName + case 1: + if(subject_alt_names.length > 0) + { + for(var k = 0; k < subject_alt_names.length; k++) + { + if(subject_alt_names[k].NameType === 2) // dNSName + { + valueExists = true; + group_permitted = group_permitted || compare_dNSName(subject_alt_names[k].Name, group[j].base.Name); + } + } + } + break; + // #endregion + // #region directoryName + case 2: + valueExists = true; + group_permitted = compare_directoryName(_this.certs[i].subject, group[j].base.Name); + break; + // #endregion + // #region uniformResourceIdentifier + case 3: + if(subject_alt_names.length > 0) + { + for(var k = 0; k < subject_alt_names.length; k++) + { + if(subject_alt_names[k].NameType === 6) // uniformResourceIdentifier + { + valueExists = true; + group_permitted = group_permitted || compare_uniformResourceIdentifier(subject_alt_names[k].Name, group[j].base.Name); + } + } + } + break; + // #endregion + // #region iPAddress + case 4: + if(subject_alt_names.length > 0) + { + for(var k = 0; k < subject_alt_names.length; k++) + { + if(subject_alt_names[k].NameType === 7) // iPAddress + { + valueExists = true; + group_permitted = group_permitted || compare_iPAddress(subject_alt_names[k].Name, group[j].base.Name); + } + } + } + break; + // #endregion + // #region default + + default: + // #endregion + } + + if(group_permitted) + break; + } + + if((group_permitted === false) && (group.length > 0) && valueExists) + { + policy_result.result = false; + policy_result.result_code = 41; + policy_result.result_message = "Failed to meet \"permitted sub-trees\" name constraint"; + + return new Promise(function(resolve, reject) + { + reject(policy_result); + }); + } + } + // #endregion + // #endregion + + // #region Checking for "excluded sub-trees" + var excluded = false; + + for(var j = 0; j < excluded_subtrees.length; j++) + { + switch(excluded_subtrees[j].base.NameType) + { + // #region rfc822Name + case 1: + if(subject_alt_names.length >= 0) + { + for(var k = 0; k < subject_alt_names.length; k++) + { + if(subject_alt_names[k].NameType === 1) // rfc822Name + excluded = excluded || compare_rfc822Name(subject_alt_names[k].Name, excluded_subtrees[j].base.Name); + } + } + else // Try to find out "emailAddress" inside "subject" + { + for(var k = 0; k < _this.subject.types_and_values.length; k++) + { + if((_this.subject.types_and_values[k].type === "1.2.840.113549.1.9.1") || // PKCS#9 e-mail address + (_this.subject.types_and_values[k].type === "0.9.2342.19200300.100.1.3")) // RFC1274 "rfc822Mailbox" e-mail address + { + excluded = excluded || compare_rfc822Name(_this.subject.types_and_values[k].value.value_block.value, excluded_subtrees[j].base.Name); + } + } + } + break; + // #endregion + // #region dNSName + case 2: + if(subject_alt_names.length > 0) + { + for(var k = 0; k < subject_alt_names.length; k++) + { + if(subject_alt_names[k].NameType === 2) // dNSName + excluded = excluded || compare_dNSName(subject_alt_names[k].Name, excluded_subtrees[j].base.Name); + } + } + break; + // #endregion + // #region directoryName + case 4: + excluded = excluded || compare_directoryName(_this.certs[i].subject, excluded_subtrees[j].base.Name); + break; + // #endregion + // #region uniformResourceIdentifier + case 6: + if(subject_alt_names.length > 0) + { + for(var k = 0; k < subject_alt_names.length; k++) + { + if(subject_alt_names[k].NameType === 6) // uniformResourceIdentifier + excluded = excluded || compare_uniformResourceIdentifier(subject_alt_names[k].Name, excluded_subtrees[j].base.Name); + } + } + break; + // #endregion + // #region iPAddress + case 7: + if(subject_alt_names.length > 0) + { + for(var k = 0; k < subject_alt_names.length; k++) + { + if(subject_alt_names[k].NameType === 7) // iPAddress + excluded = excluded || compare_iPAddress(subject_alt_names[k].Name, excluded_subtrees[j].base.Name); + } + } + break; + // #endregion + // #region default + + default: // No action, but probably here we need to create a warning for "malformed constraint" + // #endregion + } + + if(excluded) + break; + } + + if(excluded === true) + { + policy_result.result = false; + policy_result.result_code = 42; + policy_result.result_message = "Failed to meet \"excluded sub-trees\" name constraint"; + + return new Promise(function(resolve, reject) + { + reject(policy_result); + }); + } + // #endregion + + // #region Append "cert_..._subtrees" to "..._subtrees" + permitted_subtrees = permitted_subtrees.concat(cert_permitted_subtrees); + excluded_subtrees = excluded_subtrees.concat(cert_excluded_subtrees); + // #endregion + } + // #endregion + + return policy_result; + } + ); + // #endregion + + return sequence; + }; + //************************************************************************************** + // #endregion + //************************************************************************************** +} +)(typeof exports !== "undefined" ? exports : window); \ No newline at end of file diff --git a/express-server/node_modules/pkijs/package.json b/express-server/node_modules/pkijs/package.json new file mode 100644 index 00000000..e303f36f --- /dev/null +++ b/express-server/node_modules/pkijs/package.json @@ -0,0 +1,96 @@ +{ + "_args": [ + [ + "pkijs@^1.3.27", + "/nodeapps/https-test/greenlock-express.js/node_modules/certpem" + ] + ], + "_from": "pkijs@>=1.3.27 <2.0.0", + "_id": "pkijs@1.3.33", + "_inCache": true, + "_installable": true, + "_location": "/pkijs", + "_nodeVersion": "5.8.0", + "_npmOperationalInternal": { + "host": "packages-18-east.internal.npmjs.com", + "tmp": "tmp/pkijs-1.3.33.tgz_1479707633813_0.7746773960534483" + }, + "_npmUser": { + "email": "yury@strozhevsky.com", + "name": "yury.strozhevsky" + }, + "_npmVersion": "3.10.7", + "_phantomChildren": {}, + "_requested": { + "name": "pkijs", + "raw": "pkijs@^1.3.27", + "rawSpec": "^1.3.27", + "scope": null, + "spec": ">=1.3.27 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/certpem" + ], + "_resolved": "https://registry.npmjs.org/pkijs/-/pkijs-1.3.33.tgz", + "_shasum": "a689ef62113b7c348e1ffc09965d2239e5bb4c92", + "_shrinkwrap": null, + "_spec": "pkijs@^1.3.27", + "_where": "/nodeapps/https-test/greenlock-express.js/node_modules/certpem", + "author": { + "email": "yury@strozhevsky.com", + "name": "Yury Strozhevsky" + }, + "bugs": { + "url": "https://github.com/GlobalSign/PKI.js/issues" + }, + "contributors": [ + { + "name": "Ryan Hurst", + "email": "rmh@unmitigatedrisk.com" + } + ], + "dependencies": {}, + "description": "Public Key Infrastructure (PKI) is the basis of how identity and key management is performed on the web today. PKIjs is a pure JavaScript library implementing the formats that are used in PKI applications. It is built on WebCrypto and aspires to make it p", + "devDependencies": {}, + "directories": {}, + "dist": { + "shasum": "a689ef62113b7c348e1ffc09965d2239e5bb4c92", + "tarball": "http://registry.npmjs.org/pkijs/-/pkijs-1.3.33.tgz" + }, + "gitHead": "41b63af760cacb565dd850fb3466ada4ca163eff", + "homepage": "https://github.com/GlobalSign/PKI.js#readme", + "keywords": [ + "OCSP", + "PKCS", + "Web Cryptography API", + "WebCrypto", + "X.509", + "certificate", + "cms", + "crl", + "encrypted", + "enveloped", + "timestamp" + ], + "main": "org/pkijs/x509_simpl.js", + "maintainers": [ + { + "name": "peculiarventures", + "email": "info@peculiarventures.com" + }, + { + "name": "yury.strozhevsky", + "email": "yury@strozhevsky.com" + } + ], + "name": "pkijs", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/GlobalSign/PKI.js.git" + }, + "scripts": {}, + "version": "1.3.33" +} diff --git a/express-server/node_modules/pyconf/LICENSE b/express-server/node_modules/pyconf/LICENSE new file mode 100644 index 00000000..8f71f43f --- /dev/null +++ b/express-server/node_modules/pyconf/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/express-server/node_modules/pyconf/README.md b/express-server/node_modules/pyconf/README.md new file mode 100644 index 00000000..f31e6b25 --- /dev/null +++ b/express-server/node_modules/pyconf/README.md @@ -0,0 +1,62 @@ +# pyconf.js +formerly `node-config-python` + +Read and write python config files non-destructively (preserves comments and line-order) + +Turns this kind of thing: + +```python +foo = True +bar = None +baz = whatever +qux = apples,bananas +``` + +Into this kind of thing: + +```javascript +{ foo: true +, bar: null +, baz: "whatever" +, qux: ["apples", "bananas"] +} +``` + +(comments are stored in meta-data keys `__lines` and `__keys`) + +## Install + +```bash +npm install --save pyconf +``` + +## Usage + +```javascript +var pyconf = require('pyconf'); + +// alias for fs.readFile() then pyconf.parse() +pyconf.readFile("/path/to/foo.conf", function (err, obj) { + console.log(obj); +}); + +// alias for pyconf.stringify() then safeReplace.writeFile() +pyconf.writeFile("/path/to/foo.conf", obj, function (err, obj) { + console.log("wrote file"); +}); +``` + +Note: the `writeFile` function uses `safe-replace` so that it will work even in environments where race conditions are possible and will also create a backup file `whatever.conf.bak` of the config being overwritten. + +## API + +```javascript +pyconf + .parse(str, cb) // => err, object + + .stringify(obj, cb) // => err, text + + .readFile(filename, cb) // => err, object + + .writeFile(filename, obj, cb) // => err +``` diff --git a/express-server/node_modules/pyconf/example.conf b/express-server/node_modules/pyconf/example.conf new file mode 100644 index 00000000..4ed27faa --- /dev/null +++ b/express-server/node_modules/pyconf/example.conf @@ -0,0 +1,62 @@ +cert = /etc/letsencrypt/live/example.com/cert.pem +privkey = /etc/letsencrypt/live/example.com/privkey.pem +chain = /etc/letsencrypt/live/example.com/chain.pem +fullchain = /etc/letsencrypt/live/example.com/fullchain.pem + +# Options and defaults used in the renewal process +[renewalparams] +apache_enmod = a2enmod +no_verify_ssl = False +ifaces = None +apache_dismod = a2dismod +register_unsafely_without_email = False +uir = None +installer = none +config_dir = /etc/letsencrypt +text_mode = False +func = +prepare = False +work_dir = /var/lib/letsencrypt +tos = True +init = False +http01_port = 80 +duplicate = False +key_path = None +nginx = False +fullchain_path = /home/user/letsencrypt/chain.pem +email = user@example.com +csr = None +agree_dev_preview = None +redirect = None +verbose_count = -3 +config_file = None +renew_by_default = False +hsts = False +authenticator = webroot +domains = example.com, +rsa_key_size = 2048 +checkpoints = 1 +manual_test_mode = False +apache = False +cert_path = /home/user/letsencrypt/cert.pem +webroot_path = /srv/www/example.com/, +strict_permissions = False +apache_server_root = /etc/apache2 +account = f4c33502df3789849f617944253b35ae +manual_public_ip_logging_ok = False +chain_path = /home/user/letsencrypt/chain.pem +standalone = False +manual = False +server = https://acme-v01.api.letsencrypt.org/directory +standalone_supported_challenges = "http-01,tls-sni-01" +webroot = True +apache_init_script = None +user_agent = None +apache_ctl = apache2ctl +apache_le_vhost_ext = -le-ssl.conf +debug = False +tls_sni_01_port = 443 +logs_dir = /var/log/letsencrypt +configurator = None +[[webroot_map]] +example.com = /srv/www/example.com/ diff --git a/express-server/node_modules/pyconf/index.js b/express-server/node_modules/pyconf/index.js new file mode 100644 index 00000000..391a382c --- /dev/null +++ b/express-server/node_modules/pyconf/index.js @@ -0,0 +1,184 @@ +'use strict'; + +var fs = require('fs'); +var sfs = require('safe-replace').create(); + +function snakeCase(key) { + // TODO let user supply list of exceptions + if ('tlsSni01Port' === key) { + return 'tls_sni_01_port'; + } + /* + else if ('http01Port' === key) { + return 'http01-port'; + } + */ + else { + return key.replace(/([A-Z])/g, '_$1').toLowerCase(); + } +} + +function uc(match, c) { + return c.toUpperCase(); +} + +function camelCase(key) { + return key.replace(/_([a-z0-9])/g, uc); +} + +function parsePythonConf(str, cb) { + var keys = {}; + var obj = {}; + var lines = str.split('\n'); + + lines.forEach(function (line, i) { + line = line.replace(/#.*/, '').trim(); + + if (!line) { return; } + + var parts = line.split('='); + var pykey = parts.shift().trim(); + var key = camelCase(pykey); + var val = parts.join('=').trim(); + + if ('True' === val) { + val = true; + } + else if ('False' === val) { + val = false; + } + else if ('None' === val || '' === val) { + val = null; + } + else if (/,/.test(val) && !/^"[^"]*"$/.test(val)) { + val = val.split(',').map(function(x) { return x.trim(); }); + } + else if (/^-?[0-9]+$/.test(val)) { + val = parseInt(val, 10); + } + + obj[key] = val; + if ('undefined' !== typeof keys[key]) { + console.warn("unexpected duplicate key '" + key + "': '" + val + "'"); + } + + keys[key] = i; + }); + + // we want to be able to rewrite the file with comments, etc + obj.__keys = keys; + obj.__lines = lines; + + cb(null, obj); +} + +function toPyVal(val) { + if (null === val || '' === val) { + return 'None'; + } + else if (true === val) { + return 'True'; + } + else if (false === val) { + return 'False'; + } + else if ('string' === typeof val) { + return val; + } + else if ('number' === typeof val) { + return val; + } + else if (Array.isArray(val)) { + val = val.join(','); + if (-1 === val.indexOf(',')) { + val += ','; // disambiguates value from array with one element + } + return val; + } + + return val && JSON.stringify(val); +} + +function stringifyPythonConf(obj, cb) { + var endline; + + // nix the final newline + if (!obj.__lines[obj.__lines.length - 1].trim()) { + endline = obj.__lines.pop(); + } + + Object.keys(obj).forEach(function (key) { + if ('__' === key.slice(0, 2)) { + return; + } + + var pykey = snakeCase(key); + var pyval = toPyVal(obj[key]); + var num = obj.__keys[key]; + var comment = ''; + + if ('undefined' === typeof pyval) { + if ('number' === typeof num) { + pyval = 'None'; + } else { + return; + } + } + + if ('number' !== typeof num) { + obj.__lines.push(pykey + ' = ' + pyval); + obj.__keys[key] = obj.__lines.length - 1; + return; + } + + if ('[' === pykey[0]) { + return; + } + + if (!obj.__lines[num] || !obj.__lines[num].indexOf) { + console.warn('[pyconf] WARN index past array length:'); + console.log(obj.__lines.length, num, obj.__lines[num]); + return; + } + + // restore comments + if (-1 !== obj.__lines[num].indexOf('#')) { + comment = obj.__lines[num].replace(/.*?(\s*#.*)/, '$1'); + } + + obj.__lines[num] = pykey + ' = ' + pyval + comment; + }); + + if ('string' === typeof endline) { + obj.__lines.push(endline); + } + + cb(null, obj.__lines.join('\n')); +} + +function writePythonConfFile(pathname, obj, cb) { + // TODO re-read file? + stringifyPythonConf(obj, function (err, text) { + sfs.writeFileAsync(pathname, text, 'utf8').then(function () { + cb(null, null); + }, function (err) { + cb(err); + }); + }); +} + +function parsePythonConfFile(pathname, cb) { + fs.readFile(pathname, 'utf8', function (err, text) { + if (err) { + cb(err); + return; + } + + parsePythonConf(text, cb); + }); +} + +module.exports.parse = parsePythonConf; +module.exports.readFile = parsePythonConfFile; +module.exports.stringify = stringifyPythonConf; +module.exports.writeFile = writePythonConfFile; diff --git a/express-server/node_modules/pyconf/package.json b/express-server/node_modules/pyconf/package.json new file mode 100644 index 00000000..a4960351 --- /dev/null +++ b/express-server/node_modules/pyconf/package.json @@ -0,0 +1,90 @@ +{ + "_args": [ + [ + "pyconf@^1.1.5", + "/nodeapps/https-test/greenlock-express.js/node_modules/le-store-certbot" + ] + ], + "_from": "pyconf@>=1.1.5 <2.0.0", + "_hasShrinkwrap": false, + "_id": "pyconf@1.1.6", + "_inCache": true, + "_installable": true, + "_location": "/pyconf", + "_nodeVersion": "10.6.0", + "_npmOperationalInternal": { + "host": "s3://npm-registry-packages", + "tmp": "tmp/pyconf_1.1.6_1536003539653_0.6897520845380114" + }, + "_npmUser": { + "email": "coolaj86@gmail.com", + "name": "coolaj86" + }, + "_npmVersion": "6.1.0", + "_phantomChildren": {}, + "_requested": { + "name": "pyconf", + "raw": "pyconf@^1.1.5", + "rawSpec": "^1.1.5", + "scope": null, + "spec": ">=1.1.5 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/le-store-certbot" + ], + "_resolved": "https://registry.npmjs.org/pyconf/-/pyconf-1.1.6.tgz", + "_shasum": "ebd8e8e8aaba5d48c35423b81b61429323e287a2", + "_shrinkwrap": null, + "_spec": "pyconf@^1.1.5", + "_where": "/nodeapps/https-test/greenlock-express.js/node_modules/le-store-certbot", + "author": { + "email": "coolaj86@gmail.com", + "name": "AJ ONeal", + "url": "https://coolaj86.com/" + }, + "bugs": { + "url": "https://git.coolaj6.com/coolaj86/pyconf.js/issues" + }, + "dependencies": { + "safe-replace": "^1.0.2" + }, + "description": "Read and write python config files non-destructively (preserves comments)", + "devDependencies": {}, + "directories": {}, + "dist": { + "fileCount": 6, + "integrity": "sha512-4ujjwqch6nViWduSLc3/QFrDdJJAvAE7NRBarSGLANwh0tNW0MbXeJE8ZziJZvzRnUEN5scYwsS+ItYU1uj6dQ==", + "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbjY3UCRA9TVsSAnZWagAAHFoP/1ZNFI4EZCpCrm10V3CS\ni776vxoYtEy8UdK1Pndp4SV/zF+zAJZkxDRpoks6hhHpLV1+T2mK6Fy5mqGn\nC5qZct1h/7y3g/uEErmBXXNs1JCBWqtgLIK69MGkCsIHcMtOcSN9nxsreitL\ngwYSEShA06HIMSTc9exqMThD4CwOnxV3b0G6zfCeGwaE+F571BDTfsCjmAS1\nDYyX6+QjutMuvjkcWDWZ6gjFHXq4FBXzMciNWag3Ts21ndaRFtcmugL3hTmZ\n16SHKQ/SeK+L1yQhhatKO4yt3JL2YXz7PAKSh9rh7JNLMn79pUcE7Xq3qOyq\nSM4GpGxoCPVwFDJqYLCSGuzLY1HLByJfNRenoUnTMiijPco0bXG1jQoQ1pxK\nHh1kRBfHAUh3+WaVjfKTZYKNhS5ly3gIopCbbypJYeXE6MRDcotYLgZb5Ao8\nlLzt+ayQEwDnLTvi69LHs4lw5hwaw9XivgAWXq4yPrIdJS0ZPSKEkUcrR08d\n0xeStTSLZmJHpvex4y32t21AsCYmu0IgPkIg0vXFLE7InM4dSwCtLu/zpZFF\nK9bzuClgMOPk+4iLTnCZ6PfXRJfA6u/EYhKB4GrijUIRI5jjOX7zWuJ8mlh6\nIz9qigrwST5RGBGjXyUYKaN2BV5uaIfARfe1V6PX/xEBQJfQXucczbJxVTUZ\nFeaH\r\n=iDqw\r\n-----END PGP SIGNATURE-----\r\n", + "shasum": "ebd8e8e8aaba5d48c35423b81b61429323e287a2", + "tarball": "https://registry.npmjs.org/pyconf/-/pyconf-1.1.6.tgz", + "unpackedSize": 19641 + }, + "gitHead": "6f6deae8fa5e20a4c9684f1a503e697bb70e8dd7", + "homepage": "https://git.coolaj6.com/coolaj86/pyconf.js#readme", + "keywords": [ + "comments", + "conf", + "config", + "python" + ], + "license": "(MIT OR Apache-2.0)", + "main": "index.js", + "maintainers": [ + { + "name": "coolaj86", + "email": "coolaj86@gmail.com" + } + ], + "name": "pyconf", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "https://git.coolaj6.com/coolaj86/pyconf.js.git" + }, + "scripts": { + "test": "node test.js" + }, + "version": "1.1.6" +} diff --git a/express-server/node_modules/pyconf/test.js b/express-server/node_modules/pyconf/test.js new file mode 100644 index 00000000..4afd864c --- /dev/null +++ b/express-server/node_modules/pyconf/test.js @@ -0,0 +1,26 @@ +'use strict'; +//var pyconf = require('pyconf'); +var pyconf = require('./'); + +pyconf.readFile('doesnt-exist.conf', function (err, obj) { + if (!err || obj) { + console.error("didn't get an error (or also got an object) when testing on non-existant file"); + process.exit(1); + } +}); +pyconf.readFile('example.conf', function (err, obj) { + if (err) { + console.error(err.stack); + return; + } + + pyconf.writeFile('example.conf.new', obj, function (err) { + if (err) { + console.error(err.stack); + return; + } + + console.log("Run this command to check that the outputs are the same:"); + console.log(" diff example.conf example.conf.new"); + }); +}); diff --git a/express-server/node_modules/redirect-https/LICENSE b/express-server/node_modules/redirect-https/LICENSE new file mode 100644 index 00000000..8f71f43f --- /dev/null +++ b/express-server/node_modules/redirect-https/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/express-server/node_modules/redirect-https/README.md b/express-server/node_modules/redirect-https/README.md new file mode 100644 index 00000000..5b691866 --- /dev/null +++ b/express-server/node_modules/redirect-https/README.md @@ -0,0 +1,113 @@ +# redirect-https + +Secure-by-default redirects from HTTP to HTTPS. + +* Browsers get a 301 + Location redirect +* Only developers, bots, and APIs see security warning (advising to use HTTPS) +* Always uses meta redirect as a fallback, for everyone +* '/' always gets a 301 (for `curl | bash` installers) +* minimally configurable, don't get fancy + +See + +## Installation and Usage + +```bash +npm install --save redirect-https +``` + +```js +'use strict'; + +var express = require('express'); +var app = express(); + +app.use('/', require('redirect-https')({ + body: '' +})); + +module.exports = app; +``` + +## Options + +```js +{ port: 443 // defaults to 443 +, body: '' // defaults to an html comment to use https +, trustProxy: true // useful if you haven't set this option in express +, browsers: 301 // issue 301 redirect if the user-agent contains "Mozilla/" +, apis: 'meta' // issue meta redirects to non-browsers +} +``` + +* This module will call `next()` if the connection is already tls / https. +* If `trustProxy` is true, and `X-Forward-Proto` is https, `next()` will be called. +* If you use `{{URL}}` in the body text it will be replaced with a URI encoded and HTML escaped url (it'll look just like it is) +* If you use `{{HTML_URL}}` in the body text it will be replaced with a URI decoded and HTML escaped url (it'll look just like it would in Chrome's URL bar) + +## Advanced Options + +For the sake of `curl | bash` installers and the like there is also the option to cause bots and apis (i.e. curl) +to get a certain redirect for an exact path match: + +```js +{ paths: [ + { match: '/' + , redirect: 301 + } + , { match: /^\/$/ + , redirect: 301 + } + ] +} +``` + +If you're using this, you're probably getting too fancy (but hey, I get too fancy sometimes too). + +## Demo + +```javascript +'use strict'; + +var http = require('http'); +var server = http.createServer(); +var securePort = process.argv[2] || 8443; +var insecurePort = process.argv[3] || 8080; + +server.on('request', require('redirect-https')({ + port: securePort +, body: '' +, trustProxy: true // default is false +})); + +server.listen(insecurePort, function () { + console.log('Listening on http://localhost.pplwink.com:' + server.address().port); +}); +``` + +# Meta redirect by default, but why? + +When something is broken (i.e. insecure), you don't want it to kinda work, you want developers to notice. + +Using a meta redirect will break requests from `curl` and api calls from a programming language, but still have all the SEO and speed benefits of a normal `301`. + +```html + + + + + +``` + +# Other strategies + +If your application is properly separated between static assets and api, then it would probably be more beneficial to return a 200 OK with an error message inside + +# Security + +The incoming URL is already URI encoded by the browser but, just in case, I run an html escape on it +so that no malicious links of this sort will yield unexpected behavior: + + * `http://localhost.pplwink.com:8080/">` + * `http://localhost.pplwink.com:8080/';URL=http://example.com` + * `http://localhost.pplwink.com:8080/;URL=http://example.com` diff --git a/express-server/node_modules/redirect-https/example.js b/express-server/node_modules/redirect-https/example.js new file mode 100644 index 00000000..239c0189 --- /dev/null +++ b/express-server/node_modules/redirect-https/example.js @@ -0,0 +1,15 @@ +'use strict'; + +var http = require('http'); +var server = http.createServer(); +var port = process.argv[2] || 8080; + +server.on('request', require('./')({ + port: 8443 +, body: 'Redirecting to {{HTML_URL}}' +, trustProxy: true // default is false +})); + +server.listen(port, function () { + console.log('Listening on http://localhost.daplie.com:' + server.address().port); +}); diff --git a/express-server/node_modules/redirect-https/index.js b/express-server/node_modules/redirect-https/index.js new file mode 100644 index 00000000..e3f3b9a2 --- /dev/null +++ b/express-server/node_modules/redirect-https/index.js @@ -0,0 +1,97 @@ +'use strict'; + +module.exports = function (opts) { + var escapeHtml = require('escape-html'); + + if (!opts) { + opts = {}; + } + if (!isFinite(opts.port)) { + opts.port = 443; + } + if (!opts.browsers) { + opts.browsers = 301; + } + if (!opts.apis) { + opts.apis = 'meta'; + } + if (!Array.isArray(opts.paths)) { + opts.paths = [ { match: '/' } ]; + } + if (!('body' in opts)) { + opts.body = ""; + } + opts.body = opts.body.replace(/{{\s+PORT\s+}}/ig, opts.port); + + return function (req, res, next) { + if (req.connection.encrypted + || 'https' === req.protocol + || (opts.trustProxy && 'https' === req.headers['x-forwarded-proto']) + ) { + next(); + return; + } + + var url = (req.originalUrl || req.url); + // We don't want chrome showing the "Not Secure" badge during the redirect. + var probablyBrowser = (0 === (req.headers['user-agent']||'').indexOf('Mozilla/')); + // But we don't want devs, APIs, or Bots to accidentally browse insecure. + var redirect = probablyBrowser ? opts.browsers : opts.apis; + var host = req.headers.host || ''; + if (!/:\d+/.test(host) && 443 !== opts.port) { + // we are using standard port 80, but we aren't using standard port 443 + host += ':80'; + } + var newLocation = 'https://' + + host.replace(/:\d+/, ':' + opts.port) + url + ; + + //var encodedLocation = encodeURI(newLocation); + var escapedLocation = escapeHtml(newLocation); + var decodedLocation; + try { + decodedLocation = decodeURIComponent(newLocation); + } catch(e) { + decodedLocation = newLocation; // "#/error/?error_message=" + e.toString(); + } + + var body = opts.body + .replace(/{{\s*HTML_URL\s*}}/ig, escapeHtml(decodedLocation)) + .replace(/{{\s*URL\s*}}/ig, escapedLocation) + .replace(/{{\s*UNSAFE_URL\s*}}/ig, newLocation) + ; + + var metaRedirect = '' + + '\n' + + '\n' + //+ ' \n' + + ' \n' + + '\n' + + '\n' + body + '\n\n' + + '\n' + ; + var pathMatch; + + opts.paths.some(function (p) { + if (!p.match) { + // ignore + } else if ('string' === typeof p.match) { + pathMatch = (url === p.match) && (p.redirect || 301); + } else { + pathMatch = p.match.test && p.match.test(url) && (p.redirect || 301); + } + if (pathMatch) { + redirect = pathMatch; + } + return pathMatch; + }); + // If it's not a non-0 number (because null is 0) then 'meta' is assumed. + if (redirect && isFinite(redirect)) { + res.statusCode = redirect; + res.setHeader('Location', newLocation); + } + res.setHeader('Content-Type', 'text/html; charset=utf-8'); + res.end(metaRedirect); + }; +}; diff --git a/express-server/node_modules/redirect-https/package.json b/express-server/node_modules/redirect-https/package.json new file mode 100644 index 00000000..c0c398d7 --- /dev/null +++ b/express-server/node_modules/redirect-https/package.json @@ -0,0 +1,93 @@ +{ + "_args": [ + [ + "redirect-https@^1.1.5", + "/nodeapps/https-test/greenlock-express.js" + ] + ], + "_from": "redirect-https@>=1.1.5 <2.0.0", + "_hasShrinkwrap": false, + "_id": "redirect-https@1.3.0", + "_inCache": true, + "_installable": true, + "_location": "/redirect-https", + "_nodeVersion": "10.6.0", + "_npmOperationalInternal": { + "host": "s3://npm-registry-packages", + "tmp": "tmp/redirect-https_1.3.0_1538526323287_0.744062313082948" + }, + "_npmUser": { + "email": "coolaj86@gmail.com", + "name": "coolaj86" + }, + "_npmVersion": "6.1.0", + "_phantomChildren": {}, + "_requested": { + "name": "redirect-https", + "raw": "redirect-https@^1.1.5", + "rawSpec": "^1.1.5", + "scope": null, + "spec": ">=1.1.5 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/" + ], + "_resolved": "https://registry.npmjs.org/redirect-https/-/redirect-https-1.3.0.tgz", + "_shasum": "54a1bceacddad0c3178d435bcc8d6420b63f087a", + "_shrinkwrap": null, + "_spec": "redirect-https@^1.1.5", + "_where": "/nodeapps/https-test/greenlock-express.js", + "author": { + "email": "coolaj86@gmail.com", + "name": "AJ ONeal", + "url": "https://coolaj86.com/" + }, + "bugs": { + "url": "https://git.coolaj86.com/coolaj86/redirect-https.js/issues" + }, + "dependencies": { + "escape-html": "^1.0.3" + }, + "description": "Redirect from HTTP to HTTPS using meta redirects", + "devDependencies": {}, + "directories": {}, + "dist": { + "fileCount": 6, + "integrity": "sha512-9GzwI/+Cqw3jlSg0CW6TgBQbhiVhkHSDvW8wjgRQ9IK34wtxS71YJiQeazSCSEqbvowHCJuQZgmQFl1xUHKEgg==", + "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbtAxzCRA9TVsSAnZWagAAUHoP/Ah3a3Bh44ZUan+FgcpT\nT7TSSXiJN378hbnYNb0qUdlx2mevKhcGsmnXQvb11CILSjiUxHmqT7qyM/wj\nbyjxBMYM3809dJupBi+ut999bJZjO2Egdtn/MKTWEByQkeLNEPXOWwoaQHJJ\nw8GFvUi8u4gw6etlfCC/jIfPpVF2/V+5o7PwqsYBC6hipqyPWVCOfKDKZnSP\nhVSjtwMmUe3lGc3eAf75XWQsXDq7d13tcG7c9U+0IISE+6QAAS2gmb2e9ZNM\nh1OWlxFMhcqceSr2ocCuCR3O/K8lJp0WH5tYm8A/1XE96JvLSsm4kObCuHen\nkImwjNAwva9mn+4yrY3PhDO5h5zrpwVpgFQVb4Q7BCMXADSNP9Rx/kpHZF9z\nmApgxy+3cxk+fHYePgWVa7RWS3ZHpLoFc/9j9qXsr30lG/8Uxbk5kdRaa9iN\neuf26FoEqOIS9Fc49rA+t3F4YZBu0bRvn4t0KBoPt4eSDKl2sMkJabZqzFE6\nYB3NMvOctrgEwh+nQG4DplyL625P6OEE3wsmIRtbcDfNCdszmh6aLh87XbvE\ny2U7B0HNA026KJ+2xiZubSlHvePLrtDBoNC+1n/ttE+0daPw2PogxmPPtJ/L\n5QLKEKAbM6y5KgvfJifmYJPnby+7Yb2MWhf5y7MDrI4e99jEDQ8YhDko0BBm\nCoQH\r\n=64bZ\r\n-----END PGP SIGNATURE-----\r\n", + "shasum": "54a1bceacddad0c3178d435bcc8d6420b63f087a", + "tarball": "https://registry.npmjs.org/redirect-https/-/redirect-https-1.3.0.tgz", + "unpackedSize": 21004 + }, + "gitHead": "fd044d6467098ade85a6c8c3c563f4f1f5120455", + "homepage": "https://git.coolaj86.com/coolaj86/redirect-https.js#readme", + "keywords": [ + "force", + "http", + "https", + "location", + "meta", + "redirect", + "upgrade" + ], + "license": "(MIT OR Apache-2.0)", + "main": "index.js", + "maintainers": [ + { + "name": "coolaj86", + "email": "coolaj86@gmail.com" + } + ], + "name": "redirect-https", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://git.coolaj86.com/coolaj86/redirect-https.js.git" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "version": "1.3.0" +} diff --git a/express-server/node_modules/redirect-https/test.js b/express-server/node_modules/redirect-https/test.js new file mode 100644 index 00000000..6ad687a4 --- /dev/null +++ b/express-server/node_modules/redirect-https/test.js @@ -0,0 +1,77 @@ +'use strict'; + +var opts = { port: 0 }; +var redirect = require('./')(opts); + +function r80to443() { + // using port 80 and 443 + opts.port = 443; + var req = { connection: {}, headers: { host: 'example.com' }, url: '/path/to/somewhere.html' }; + var res = { + setHeader: function () {} + , end: function (body) { + if (!/:/.test(body)) { + throw new Error("test didn't pass with port 80 redirecting to 443"); + } + console.log('PASS: 80 to 443'); + } + }; + var next = function () {}; + redirect(req, res, next); +} + +function r80to8443() { + // using port 80, but not 443 + opts.port = 8443; + var req = { connection: {}, headers: { host: 'example.com' }, url: '/path/to/somewhere.html' }; + var res = { + setHeader: function () {} + , end: function (body) { + if (!/:8443/.test(body)) { + throw new Error("test didn't pass with port 80 redirecting to non-443"); + } + console.log('PASS: 80 to 8443'); + } + }; + var next = function () {}; + redirect(req, res, next); +} + +function r4080to8443() { + // using port 80 and 443 + opts.port = 8443; + var req = { connection: {}, headers: { host: 'example.com:4080' }, url: '/path/to/somewhere.html' }; + var res = { + setHeader: function () {} + , end: function (body) { + if (!/:8443/.test(body)) { + throw new Error("test didn't pass with port 4080 redirecting to 8443"); + } + console.log('PASS: 4080 to 8443'); + } + }; + var next = function () {}; + redirect(req, res, next); +} + +function r4080to443() { + // using port 80 and 443 + opts.port = 8443; + var req = { connection: {}, headers: { host: 'example.com:4080' }, url: '/path/to/somewhere.html' }; + var res = { + setHeader: function () {} + , end: function (body) { + if (/:/.test(body)) { + throw new Error("test didn't pass with port 4080 redirecting to 8443"); + } + console.log('PASS: 4080 to 8443'); + } + }; + var next = function () {}; + redirect(req, res, next); +} + +r80to443(); +r80to8443(); +r4080to8443(); +//r4080to443(); diff --git a/express-server/node_modules/rsa-compat/LICENSE b/express-server/node_modules/rsa-compat/LICENSE new file mode 100644 index 00000000..c2128786 --- /dev/null +++ b/express-server/node_modules/rsa-compat/LICENSE @@ -0,0 +1,375 @@ +Copyright 2016-2018 AJ ONeal + +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/express-server/node_modules/rsa-compat/README.md b/express-server/node_modules/rsa-compat/README.md new file mode 100644 index 00000000..2b72313c --- /dev/null +++ b/express-server/node_modules/rsa-compat/README.md @@ -0,0 +1,279 @@ +# rsa-compat.js +!["Lifetime Downloads"](https://img.shields.io/npm/dt/rsa-compat.svg "Lifetime Download Count can't be shown") +!["Monthly Downloads"](https://img.shields.io/npm/dm/rsa-compat.svg "Monthly Download Count can't be shown") +!["Weekly Downloads"](https://img.shields.io/npm/dw/rsa-compat.svg "Weekly Download Count can't be shown") + +| A [Root](https://therootcompany.com) Project. + +JavaScript RSA utils that work on Windows, Mac, and Linux with or without C compiler + +This now uses node-native RSA key generation and lightweight, zero-dependency solutions for key conversion. +However, it also optionally depends on `ursa` and `forge` for backwards compatibility with older node versions. + +This was built for the [ACME.js](https://git.coolaj86.com/coolaj86/acme.js) and +[Greenlock.js](https://git.coolaj86.com/coolaj86/greenlock.js) **Let's Encrypt** clients +and is particularly suitable for building **certbot**-like clients. + +(if you're looking for similar tools in the browser, consider [Bluecrypt](https://www.npmjs.com/search?q=bluecrypt)) + +# Install + +node.js + +```bash +npm install --save rsa-compat +``` + +### CLI + +```bash +npm install --global rsa-compat +``` + +# Usage + +CLI +--- + +You can generate keypairs on Windows, Mac, and Linux using rsa-keygen-js: + +```bash +# generates a new keypair in the current directory +rsa-keypiar-js +``` + +Examples +-------- + +Generate an RSA Keypair: + +```javascript +var RSA = require('rsa-compat').RSA; + +var options = { bitlen: 2048, exp: 65537, public: true, pem: true, internal: true }; + +RSA.generateKeypair(options, function (err, keypair) { + console.log(keypair); +}); +``` + +Here's what the object might look like: + +`console.log(keypair)`: +```javascript + +{ publicKeyPem: '-----BEGIN RSA PUBLIC KEY-----\n/*base64 pem-encoded string*/' +, privateKeyPem: '-----BEGIN RSA PRIVATE KEY-----\n/*base64 pem-encoded string*/' +, privateKeyJwk: { + kty: "RSA" + , n: '/*base64 modulus n = pq*/' + , e: '/*base64 exponent (usually 65537)*/' + , d: '/*base64 private exponent (d = e^−1 (mod ϕ(n))/' + , p: '/*base64 first prime*/' + , q: '/*base64 second prime*/' + , dp: '/*base64 first exponent for Chinese remainder theorem (dP = d (mod p−1))*/' + , dq: '/*base64 Second exponent, used for CRT (dQ = d (mod q−1))/' + , qi: '/*base64 Coefficient, used for CRT (qinv = q^−1 (mod p))*/' + } +, publicKeyJwk: { + kty: "RSA" + , n: '/*base64 modulus n = pq*/' + , e: '/*base64 exponent (usually 65537)*/' + } + +, _ursa: '/*undefined or intermediate ursa object*/' +, _ursaPublic: '/*undefined or intermediate ursa object*/' +, _forge: '/*undefined or intermediate forge object*/' +, _forgePublic: '/*undefined or intermediate forge object*/' +} +``` + +NOTE: this object is JSON safe as _ursa and _forge will be ignored + +See http://crypto.stackexchange.com/questions/6593/what-data-is-saved-in-rsa-private-key to learn a little more about the meaning of the specific fields in the JWK. + +# API Summary + +* `RSA.generateKeypair(options, cb)` + * (deprecated `RSA.generateKeypair(bitlen, exp, options, cb)`) +* `RSA.import(options)` + * (deprecated `RSA.import(keypair, options)`) +* `RSA.exportPrivatePem(keypair)` +* `RSA.exportPublicPem(keypair)` +* `RSA.exportPrivateJwk(keypair)` +* `RSA.exportPublicJwk(keypair)` +* `RSA.signJws(keypair, header, protect, payload)` + * (deprecated `RSA.signJws(keypair, payload, nonce)`) +* `RSA.generateCsrPem(keypair, names)` +* `RSA.generateCsrDerWeb64(keypair, names)` + +`keypair` can be any object with any of these keys `publicKeyPem, privateKeyPem, publicKeyJwk, privateKeyJwk` + +### RSA.generateKeypair(options, cb) + +Create a private keypair and export it as PEM, JWK, and/or internal formats + +```javascript +RSA.generateKeypair(null, function (keypair) { /*...*/ }); + +RSA.generateKeypair({ + bitlen: 2048, exp: 65537, pem: false, public: false, internal: false +}, function (keypair) { /*...*/ }); +``` + +`options`: +```javascript +{ public: false // export public keys +, pem: false // export pems +, jwk: true // export jwks +, internal: false // preserve internal intermediate formats (_ursa, _forge) +, thumbprint: false // JWK sha256 thumbprint +, fingerprint: false // NOT IMPLEMENTED (RSA key fingerprint) +} +``` + +### RSA.import(options) + +Imports keypair as JWKs and internal values `_ursa` and `_forge`. + +```javascript +var keypair = RSA.import({ type: 'RSA', privateKeyPem: '...' }); + +console.log(keypair); +``` + +```javascript +{ privateKeyPem: ..., privateKeyJwk: ..., _ursa: ..., _forge: ... } +``` + +### RSA.export*(keypair) + +You put in an object like `{ privateKeyPem: '...' }` or `{ publicKeyJwk: {} }` +and you get back the keys in the format you requested. + +Note: + +* Private keys **can** be used to export both private and public keys +* Public keys can **NOT** be used to generate private keys + +Example: + +```javascript +var keypair = { privateKeyPem: '...' }; + +keypair.publicKeyJwk = RSA.exportPublicJwk(keypair); + +console.log(keypair); +``` + +### RSA.signJws(keypair, payload, nonce) + +Generates a signature in JWS format (necessary for **certbot**/**letsencrypt**). + +```javascript +var message = "Hello, World!" +var nonce = crypto.randomBytes(16).toString('hex'); +var jws = RSA.signJws(keypair, message, nonce); + +console.log(jws); +``` + +The result looks like this: + +```javascript +{ "header": { + "alg": "RS256", + "jwk": { + "kty": "RSA", + "n": "AMJubTfOtAarnJytLE8fhNsEI8wnpjRvBXGK/Kp0675J10ORzxyMLqzIZF3tcrUkKBrtdc79u4X0GocDUgukpfkY+2UPUS/GxehUYbYrJYWOLkoJWzxn7wfoo9X1JgvBMY6wHQnTKvnzZdkom2FMhGxkLaEUGDSfsNznTTZNBBg9", + "e": "AQAB" + } + }, + "protected": "eyJub25jZSI6IjhlZjU2MjRmNWVjOWQzZWYifQ", + "payload": "JLzF1NBNCV3kfbJ5sFaFyX94fJuL2H-IzaoBN-ciiHk", + "signature": "Wb2al5SDyh5gjmkV79MK9m3sfNBBPjntSKor-34BBoGwr6n8qEnBmqB1Y4zbo-5rmvsoPmJsnRlP_hRiUY86zSAQyfbisTGrGBl0IQ7ditpkfYVm0rBWJ8WnYNqYNp8K3qcD7NW72tsy-XoWEjNlz4lWJeRdEG2Nt4CJgnREH4Y" +} +``` + +### RSA.generateCsr*(keypair, names) + +You can generate the CSR in human-readable or binary / base64 formats: + +`RSA.generateCsrPem(keypair, names)`: +```javascript +var pem = RSA.generateCsrPem(keypair, [ 'example.com', 'www.example.com' ]); + +console.log(pem); +``` + +web-safe base64 for **certbot**/**letsencrypt**: + +`RSA.generateCsrDerWeb64(keypair, names)`: +```javascript +var web64 = RSA.generateCsrDerWeb64(keypair, [ 'example.com', 'www.example.com' ]); + +console.log(web64); +``` + +# Old Node Versions + +In recent versions of node >= v10.12 native RSA key generation is fairly quick for 2048-bit keys +(though it may still be too slow for some applications with 4096-bit keys). + +In old versions, however, and especially on ARM and/or MIPS procesors, RSA key generation can be +very, very slow. + +In old node versions `ursa` can provide faster key generation, but it must be compiled. +`ursa` will not compile for new node versions, but they already include the same openssl bindings anyawy. + + +```bash +npm install --save ursa +``` + +Also, if you need **Node < v6** support: + +```bash +npm install --save buffer-v6-polyfill +``` + +## Security and Compatibility + +**TL;DR**: Use the default values 2048 and 65537 unless you have a really, really good reason to do otherwise. + +Various platforms *require* these values. + +Most security experts agree that 4096-bit is no more "secure" than 2048-bit - +a fundamental vulnerability in the RSA algorithm which causes 2048 to be broken +will most likely also cause 4096 to be broken +(i.e. if someone can prove mathematically prove P=NP or a way to predict prime numbers). +Also, many platforms +only support 2048 bit keys due to the insecurity of 1024-bit keys (which are not 1/2 secure +but rather 1/(2^1028) less secure) and the excess computational +cost of 4096-bit keys (it's not a 2x increase, it's more like a 2^2048 increase). + +As to why 65537 is even optional as a prime exponent or why it matters... no idea, +but it does matter. + +# ChangeLog: + +* v1.9.0 + * consistently handle key generation across node crypto, ursa, and forge + * move all other operations to rasha.js and rsa-csr.js +* v1.4.0 + * remove ursa as dependency (just causes confusion), but note in docs + * drop node < v6 support + +# Legal + +rsa-compat.js directly includes code from +[Rasha.js](https://git.coolaj86.com/coolaj86/rasha.js) +and +[RSA-CSR.js](https://git.coolaj86.com/coolaj86/rsa-csr.js) +(also [Root](https://therootcompany.com) projects), +retrofitted for rsa-compat. + +[rsa-compat.js](https://git.coolaj86.com/coolaj86/rsa-compat.js) | +MPL-2.0 | +[Terms of Use](https://therootcompany.com/legal/#terms) | +[Privacy Policy](https://therootcompany.com/legal/#privacy) diff --git a/express-server/node_modules/rsa-compat/bin/rsa-keygen.js b/express-server/node_modules/rsa-compat/bin/rsa-keygen.js new file mode 100644 index 00000000..e65176f5 --- /dev/null +++ b/express-server/node_modules/rsa-compat/bin/rsa-keygen.js @@ -0,0 +1,35 @@ +#!/usr/bin/env node +'use strict'; + +var RSA = require('../').RSA; +var path = require('path'); +var fs = require('fs'); + +var bitlen = 2048; +var exp = 65537; +var opts = { public: true, pem: true }; +var cwd = process.cwd(); +var privkeyPath = path.join(cwd, 'privkey.pem'); +var pubkeyPath = path.join(cwd, 'pubkey.pem'); + +if (fs.existsSync(privkeyPath)) { + console.error(privkeyPath, "already exists"); + process.exit(1); +} + +RSA.generateKeypair(bitlen, exp, opts, function (err, keypair) { + console.info(''); + console.info(''); + + fs.writeFileSync(privkeyPath, keypair.privateKeyPem, 'ascii'); + console.info(privkeyPath + ':'); + console.info(''); + console.info(keypair.privateKeyPem); + + console.info(''); + + fs.writeFileSync(pubkeyPath, keypair.publicKeyPem, 'ascii'); + console.info(pubkeyPath + ':'); + console.info(''); + console.info(keypair.publicKeyPem); +}); diff --git a/express-server/node_modules/rsa-compat/fixtures/csr.pem b/express-server/node_modules/rsa-compat/fixtures/csr.pem new file mode 100644 index 00000000..562c8b29 --- /dev/null +++ b/express-server/node_modules/rsa-compat/fixtures/csr.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBjzCB+QIBADAWMRQwEgYDVQQDEwtleGFtcGxlLmNvbTCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAwm5tN860BqucnK0sTx+E2wQjzCemNG8FcYr8qnTrvknX +Q5HPHIwurMhkXe1ytSQoGu11zv27hfQahwNSC6Sl+Rj7ZQ9RL8bF6FRhtislhY4u +SglbPGfvB+ij1fUmC8ExjrAdCdMq+fNl2SibYUyEbGQtoRQYNJ+w3OdNNk0EGD0C +AwEAAaA6MDgGCSqGSIb3DQEJDjErMCkwJwYDVR0RBCAwHoILZXhhbXBsZS5jb22C +D3d3dy5leGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOBgQCv1nj7zL0vnP11GEDb +TWlXPyT2XaFH9lYOm8By3BKrtk6rhGojlLppmNGaCEBqztebCY2T5LT6mi5lz0xc +YHJ9YC4w1yKz94//gmEMYJ+7fuILexnaeZudp9GjR3OeRWIWr/+3H0U3XnZpazGP +/qK4BCIl9HOOJbF5tyTd/CeeBg== +-----END CERTIFICATE REQUEST----- diff --git a/express-server/node_modules/rsa-compat/fixtures/csr.urlbase64 b/express-server/node_modules/rsa-compat/fixtures/csr.urlbase64 new file mode 100644 index 00000000..12dffac6 --- /dev/null +++ b/express-server/node_modules/rsa-compat/fixtures/csr.urlbase64 @@ -0,0 +1 @@ +MIIBjzCB-QIBADAWMRQwEgYDVQQDEwtleGFtcGxlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwm5tN860BqucnK0sTx-E2wQjzCemNG8FcYr8qnTrvknXQ5HPHIwurMhkXe1ytSQoGu11zv27hfQahwNSC6Sl-Rj7ZQ9RL8bF6FRhtislhY4uSglbPGfvB-ij1fUmC8ExjrAdCdMq-fNl2SibYUyEbGQtoRQYNJ-w3OdNNk0EGD0CAwEAAaA6MDgGCSqGSIb3DQEJDjErMCkwJwYDVR0RBCAwHoILZXhhbXBsZS5jb22CD3d3dy5leGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOBgQCv1nj7zL0vnP11GEDbTWlXPyT2XaFH9lYOm8By3BKrtk6rhGojlLppmNGaCEBqztebCY2T5LT6mi5lz0xcYHJ9YC4w1yKz94__gmEMYJ-7fuILexnaeZudp9GjR3OeRWIWr_-3H0U3XnZpazGP_qK4BCIl9HOOJbF5tyTd_CeeBg diff --git a/express-server/node_modules/rsa-compat/fixtures/privkey.jwk.json b/express-server/node_modules/rsa-compat/fixtures/privkey.jwk.json new file mode 100644 index 00000000..92180d01 --- /dev/null +++ b/express-server/node_modules/rsa-compat/fixtures/privkey.jwk.json @@ -0,0 +1,11 @@ +{ + "kty": "RSA", + "n": "wm5tN860BqucnK0sTx-E2wQjzCemNG8FcYr8qnTrvknXQ5HPHIwurMhkXe1ytSQoGu11zv27hfQahwNSC6Sl-Rj7ZQ9RL8bF6FRhtislhY4uSglbPGfvB-ij1fUmC8ExjrAdCdMq-fNl2SibYUyEbGQtoRQYNJ-w3OdNNk0EGD0", + "e": "AQAB", + "d": "HT8DCrv69G3n9uFNovE4yMEMqW7lX0m75eJkMze3Jj5xNOa_4qlrc-4IuuA2uuyfY72IVQRxqqqXOuvS8ZForZZk-kWSd6z45hrpbNAAHH2Rf7XwnwHY8VJrOQF3UtbktTWqHX36ITZb9Hmf18hWsIeEp8Ng7Ru9h7hNuVxKMjk", + "p": "42M69lUC-EIzYmcsZYkbf7kGhqvcwHk_h7N8TEOa7IYRP_DQL49LrSNuMHxOK9CxJ0RwajsY5o6WYBfoRC0B5w", + "q": "2uWWAmzLitMx9reZDnSQwhw1qGIQ55quEBwmBBQIe46O4SeFT0V8TED-bkVeOYQVCFHCS6GTRBoipMZtTPEYOw", + "dp": "u7Ec6lghq2p5n7AqJWWXHUZM7LzP6tAqcIjnAMyNBM9lTbIpJhjSDohAXCU_IUuR7ye-4vEFDMqFtawGPMAp4Q", + "dq": "XLhDAmPzE6rBzy-VtXnKl247jEd9wZzTfh9uOuwBa9TG0Lhcz2cvb11YaH0ZnGNGRW_cTQzzxDUN1531TlIRYQ", + "qi": "jZqnPoQJ8bCGy8hxTf7IW37cIDvwJRWxfg1S6XmbcKWzab7kxsZAbkrSEanGMMLc6ZdOrVjmCd6nnJRm9U9kjg" +} diff --git a/express-server/node_modules/rsa-compat/fixtures/privkey.pkcs1.pem b/express-server/node_modules/rsa-compat/fixtures/privkey.pkcs1.pem new file mode 100644 index 00000000..8281814e --- /dev/null +++ b/express-server/node_modules/rsa-compat/fixtures/privkey.pkcs1.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDCbm03zrQGq5ycrSxPH4TbBCPMJ6Y0bwVxivyqdOu+SddDkc8c +jC6syGRd7XK1JCga7XXO/buF9BqHA1ILpKX5GPtlD1EvxsXoVGG2KyWFji5KCVs8 +Z+8H6KPV9SYLwTGOsB0J0yr582XZKJthTIRsZC2hFBg0n7Dc5002TQQYPQIDAQAB +AoGAHT8DCrv69G3n9uFNovE4yMEMqW7lX0m75eJkMze3Jj5xNOa/4qlrc+4IuuA2 +uuyfY72IVQRxqqqXOuvS8ZForZZk+kWSd6z45hrpbNAAHH2Rf7XwnwHY8VJrOQF3 +UtbktTWqHX36ITZb9Hmf18hWsIeEp8Ng7Ru9h7hNuVxKMjkCQQDjYzr2VQL4QjNi +ZyxliRt/uQaGq9zAeT+Hs3xMQ5rshhE/8NAvj0utI24wfE4r0LEnRHBqOxjmjpZg +F+hELQHnAkEA2uWWAmzLitMx9reZDnSQwhw1qGIQ55quEBwmBBQIe46O4SeFT0V8 +TED+bkVeOYQVCFHCS6GTRBoipMZtTPEYOwJBALuxHOpYIatqeZ+wKiVllx1GTOy8 +z+rQKnCI5wDMjQTPZU2yKSYY0g6IQFwlPyFLke8nvuLxBQzKhbWsBjzAKeECQFy4 +QwJj8xOqwc8vlbV5ypduO4xHfcGc034fbjrsAWvUxtC4XM9nL29dWGh9GZxjRkVv +3E0M88Q1Dded9U5SEWECQQCNmqc+hAnxsIbLyHFN/shbftwgO/AlFbF+DVLpeZtw +pbNpvuTGxkBuStIRqcYwwtzpl06tWOYJ3qeclGb1T2SO +-----END RSA PRIVATE KEY----- diff --git a/express-server/node_modules/rsa-compat/fixtures/privkey.pkcs8.pem b/express-server/node_modules/rsa-compat/fixtures/privkey.pkcs8.pem new file mode 100644 index 00000000..cfecdc3c --- /dev/null +++ b/express-server/node_modules/rsa-compat/fixtures/privkey.pkcs8.pem @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMJubTfOtAarnJyt +LE8fhNsEI8wnpjRvBXGK/Kp0675J10ORzxyMLqzIZF3tcrUkKBrtdc79u4X0GocD +UgukpfkY+2UPUS/GxehUYbYrJYWOLkoJWzxn7wfoo9X1JgvBMY6wHQnTKvnzZdko +m2FMhGxkLaEUGDSfsNznTTZNBBg9AgMBAAECgYAdPwMKu/r0bef24U2i8TjIwQyp +buVfSbvl4mQzN7cmPnE05r/iqWtz7gi64Da67J9jvYhVBHGqqpc669LxkWitlmT6 +RZJ3rPjmGuls0AAcfZF/tfCfAdjxUms5AXdS1uS1NaodffohNlv0eZ/XyFawh4Sn +w2DtG72HuE25XEoyOQJBAONjOvZVAvhCM2JnLGWJG3+5Boar3MB5P4ezfExDmuyG +ET/w0C+PS60jbjB8TivQsSdEcGo7GOaOlmAX6EQtAecCQQDa5ZYCbMuK0zH2t5kO +dJDCHDWoYhDnmq4QHCYEFAh7jo7hJ4VPRXxMQP5uRV45hBUIUcJLoZNEGiKkxm1M +8Rg7AkEAu7Ec6lghq2p5n7AqJWWXHUZM7LzP6tAqcIjnAMyNBM9lTbIpJhjSDohA +XCU/IUuR7ye+4vEFDMqFtawGPMAp4QJAXLhDAmPzE6rBzy+VtXnKl247jEd9wZzT +fh9uOuwBa9TG0Lhcz2cvb11YaH0ZnGNGRW/cTQzzxDUN1531TlIRYQJBAI2apz6E +CfGwhsvIcU3+yFt+3CA78CUVsX4NUul5m3Cls2m+5MbGQG5K0hGpxjDC3OmXTq1Y +5gnep5yUZvVPZI4= +-----END PRIVATE KEY----- diff --git a/express-server/node_modules/rsa-compat/fixtures/signed.jwk.json b/express-server/node_modules/rsa-compat/fixtures/signed.jwk.json new file mode 100644 index 00000000..509867b5 --- /dev/null +++ b/express-server/node_modules/rsa-compat/fixtures/signed.jwk.json @@ -0,0 +1,13 @@ +{ + "header": { + "alg": "RS256", + "jwk": { + "kty": "RSA", + "n": "AMJubTfOtAarnJytLE8fhNsEI8wnpjRvBXGK_Kp0675J10ORzxyMLqzIZF3tcrUkKBrtdc79u4X0GocDUgukpfkY-2UPUS_GxehUYbYrJYWOLkoJWzxn7wfoo9X1JgvBMY6wHQnTKvnzZdkom2FMhGxkLaEUGDSfsNznTTZNBBg9", + "e": "AQAB" + } + }, + "protected": "eyJub25jZSI6IjhlZjU2MjRmNWVjOWQzZWYifQ", + "payload": "JLzF1NBNCV3kfbJ5sFaFyX94fJuL2H-IzaoBN-ciiHk", + "signature": "Wb2al5SDyh5gjmkV79MK9m3sfNBBPjntSKor-34BBoGwr6n8qEnBmqB1Y4zbo-5rmvsoPmJsnRlP_hRiUY86zSAQyfbisTGrGBl0IQ7ditpkfYVm0rBWJ8WnYNqYNp8K3qcD7NW72tsy-XoWEjNlz4lWJeRdEG2Nt4CJgnREH4Y" +} diff --git a/express-server/node_modules/rsa-compat/index.js b/express-server/node_modules/rsa-compat/index.js new file mode 100644 index 00000000..de048279 --- /dev/null +++ b/express-server/node_modules/rsa-compat/index.js @@ -0,0 +1,7 @@ +// Copyright 2016-2018 AJ ONeal. All rights reserved +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +module.exports.RSA = require('./lib/rsa.js'); diff --git a/express-server/node_modules/rsa-compat/lib/generate-privkey-forge.js b/express-server/node_modules/rsa-compat/lib/generate-privkey-forge.js new file mode 100644 index 00000000..a11def9a --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/generate-privkey-forge.js @@ -0,0 +1,57 @@ +// Copyright 2016-2018 AJ ONeal. All rights reserved +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +var Rasha = require('./rasha'); + +module.exports = function (bitlen, exp) { + var k = require('node-forge').pki.rsa + .generateKeyPair({ bits: bitlen || 2048, e: exp || 0x10001 }).privateKey; + var jwk = { + kty: "RSA" + , n: _toUrlBase64(k.n) + , e: _toUrlBase64(k.e) + , d: _toUrlBase64(k.d) + , p: _toUrlBase64(k.p) + , q: _toUrlBase64(k.q) + , dp: _toUrlBase64(k.dP) + , dq: _toUrlBase64(k.dQ) + , qi: _toUrlBase64(k.qInv) + }; + return { + publicKeyPem: Rasha.exportSync({ jwk: jwk, public: true }) + , privateKeyPem: Rasha.exportSync({ jwk: jwk }) + , privateKeyJwk: jwk + , publicKeyJwk: { + kty: jwk.kty + , n: jwk.n + , e: jwk.e + } + }; +}; + +function _toUrlBase64(fbn) { + var hex = fbn.toRadix(16); + if (hex.length % 2) { + // Invalid hex string + hex = '0' + hex; + } + while ('00' === hex.slice(0, 2)) { + hex = hex.slice(2); + } + return Buffer.from(hex, 'hex').toString('base64') + .replace(/\+/g, "-") + .replace(/\//g, "_") + .replace(/=/g,"") + ; +} + +if (require.main === module) { + var keypair = module.exports(2048, 0x10001); + console.info(keypair.privateKeyPem); + console.warn(keypair.publicKeyPem); + //console.info(keypair.privateKeyJwk); + //console.warn(keypair.publicKeyJwk); +} diff --git a/express-server/node_modules/rsa-compat/lib/generate-privkey-node.js b/express-server/node_modules/rsa-compat/lib/generate-privkey-node.js new file mode 100644 index 00000000..cfc3c8b3 --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/generate-privkey-node.js @@ -0,0 +1,39 @@ +// Copyright 2016-2018 AJ ONeal. All rights reserved +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +var Rasha = require('./rasha'); + +module.exports = function (bitlen, exp) { + var keypair = require('crypto').generateKeyPairSync( + 'rsa' + , { modulusLength: bitlen + , publicExponent: exp + , privateKeyEncoding: { + type: 'pkcs1' + , format: 'pem' + } + , publicKeyEncoding: { + type: 'pkcs1' + , format: 'pem' + } + } + ); + var result = { + publicKeyPem: keypair.publicKey.trim() + , privateKeyPem: keypair.privateKey.trim() + }; + result.publicKeyJwk = Rasha.importSync({ pem: result.publicKeyPem, public: true }); + result.privateKeyJwk = Rasha.importSync({ pem: result.privateKeyPem }); + return result; +}; + +if (require.main === module) { + var keypair = module.exports(2048, 0x10001); + console.info(keypair.privateKeyPem); + console.warn(keypair.publicKeyPem); + //console.info(keypair.privateKeyJwk); + //console.warn(keypair.publicKeyJwk); +} diff --git a/express-server/node_modules/rsa-compat/lib/generate-privkey-ursa.js b/express-server/node_modules/rsa-compat/lib/generate-privkey-ursa.js new file mode 100644 index 00000000..22672331 --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/generate-privkey-ursa.js @@ -0,0 +1,32 @@ +// Copyright 2016-2018 AJ ONeal. All rights reserved +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +var Rasha = require('./rasha'); + +module.exports = function (bitlen, exp) { + var ursa; + try { + ursa = require('ursa'); + } catch(e) { + ursa = require('ursa-optional'); + } + var keypair = ursa.generatePrivateKey(bitlen, exp); + var result = { + publicKeyPem: keypair.toPublicPem().toString('ascii').trim() + , privateKeyPem: keypair.toPrivatePem().toString('ascii').trim() + }; + result.publicKeyJwk = Rasha.importSync({ pem: result.publicKeyPem, public: true }); + result.privateKeyJwk = Rasha.importSync({ pem: result.privateKeyPem }); + return result; +}; + +if (require.main === module) { + var keypair = module.exports(2048, 0x10001); + console.info(keypair.privateKeyPem); + console.warn(keypair.publicKeyPem); + //console.info(keypair.privateKeyJwk); + //console.warn(keypair.publicKeyJwk); +} diff --git a/express-server/node_modules/rsa-compat/lib/generate-privkey.js b/express-server/node_modules/rsa-compat/lib/generate-privkey.js new file mode 100644 index 00000000..3f71b2bb --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/generate-privkey.js @@ -0,0 +1,66 @@ +// Copyright 2016-2018 AJ ONeal. All rights reserved +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +var oldver = false; + +module.exports = function (bitlen, exp) { + bitlen = parseInt(bitlen, 10) || 2048; + exp = parseInt(exp, 10) || 65537; + + try { + return require('./generate-privkey-node.js')(bitlen, exp); + } catch(e) { + if (!/generateKeyPairSync is not a function/.test(e.message)) { + throw e; + } + try { + return require('./generate-privkey-ursa.js')(bitlen, exp); + } catch(e) { + if (e.code !== 'MODULE_NOT_FOUND') { + throw e; + } + if (!oldver) { + oldver = true; + console.warn("[WARN] rsa-compat: Your version of node does not have crypto.generateKeyPair()"); + console.warn("[WARN] rsa-compat: Please update to node >= v10.12 or 'npm install ursa'"); + console.warn("[WARN] rsa-compat: Using node-forge as a fallback, but it may be unacceptably slow."); + if (/arm|mips/i.test(require('os').arch)) { + console.warn("================================================================"); + console.warn(" WARNING"); + console.warn("================================================================"); + console.warn(""); + console.warn("WARNING: You are generating an RSA key using pure JavaScript on"); + console.warn(" a VERY SLOW cpu. This could take DOZENS of minutes!"); + console.warn(""); + console.warn(" We recommend installing node >= v10.12, or 'gcc' and 'ursa'"); + console.warn(""); + console.warn("EXAMPLE:"); + console.warn(""); + console.warn(" sudo apt-get install build-essential && npm install ursa"); + console.warn(""); + console.warn("================================================================"); + } + } + try { + return require('./generate-privkey-forge.js')(bitlen, exp); + } catch(e) { + if (e.code !== 'MODULE_NOT_FOUND') { + throw e; + } + console.error("[ERROR] rsa-compat: could not generate a private key."); + console.error("None of crypto.generateKeyPair, ursa, nor node-forge are present"); + } + } + } +}; + +if (require.main === module) { + var keypair = module.exports(2048, 0x10001); + console.info(keypair.privateKeyPem); + console.warn(keypair.publicKeyPem); + //console.info(keypair.privateKeyJwk); + //console.warn(keypair.publicKeyJwk); +} diff --git a/express-server/node_modules/rsa-compat/lib/rasha/README.md b/express-server/node_modules/rsa-compat/lib/rasha/README.md new file mode 100644 index 00000000..e2d5fb27 --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rasha/README.md @@ -0,0 +1,218 @@ +[Rasha.js](https://git.coolaj86.com/coolaj86/rasha.js) · [![Build Status](https://strong-emu-11.telebit.io/api/badges/coolaj86/rasha.js/status.svg)](https://strong-emu-11.telebit.io/coolaj86/rasha.js) +========= + +Sponsored by [Root](https://therootcompany.com). +Built for [ACME.js](https://git.coolaj86.com/coolaj86/acme.js) +and [Greenlock.js](https://git.coolaj86.com/coolaj86/greenlock.js) + + + +| ~550 lines of code | 3kb gzipped | 10kb minified | 18kb with comments | + +RSA tools. Lightweight. Zero Dependencies. Universal compatibility. + +* [x] Fast and Easy RSA Key Generation +* [x] PEM-to-JWK +* [x] JWK-to-PEM +* [x] SSH "pub" format +* [ ] ECDSA + * **Need EC or ECDSA tools?** Check out [Eckles.js](https://git.coolaj86.com/coolaj86/eckles.js) + + +## Generate RSA Key + +Achieves the *fastest possible key generation* using node's native RSA bindings to OpenSSL, +then converts to JWK for ease-of-use. + +``` +Rasha.generate({ format: 'jwk' }).then(function (keypair) { + console.log(keypair.private); + console.log(keypair.public); +}); +``` + +**options** + +* `format` defaults to `'jwk'` + * `'pkcs1'` (traditional) + * `'pkcs8'` +* `modulusLength` defaults to 2048 (must not be lower) + * generally you shouldn't pick a larger key size - they're slow + * **2048** is more than sufficient + * 3072 is way, way overkill and takes a few seconds to generate + * 4096 can take about a minute to generate and is just plain wasteful + +**advanced options** + +These options are provided for debugging and should not be used. + +* `publicExponent` defaults to 65537 (`0x10001`) + +## PEM-to-JWK + +* [x] PKCS#1 (traditional) +* [x] PKCS#8, SPKI/PKIX +* [x] 2048-bit, 3072-bit, 4096-bit (and ostensibily all others) +* [x] SSH (RFC4716), (RFC 4716/SSH2) + +```js +var Rasha = require('rasha'); +var pem = require('fs') + .readFileSync('./node_modles/rasha/fixtures/privkey-rsa-2048.pkcs1.pem', 'ascii'); + +Rasha.import({ pem: pem }).then(function (jwk) { + console.log(jwk); +}); +``` + +```js +{ + "kty": "RSA", + "n": "m2ttVBxPlWw06ZmGBWVDl...QlEz7UNNj9RGps_50-CNw", + "e": "AQAB", + "d": "Cpfo7Mm9Nu8YMC_xrZ54W...Our1IdDzJ_YfHPt9sHMQQ", + "p": "ynG-t9HwKCN3MWRYFdnFz...E9S4DsGcAarIuOT2TsTCE", + "q": "xIkAjgUzB1zaUzJtW2Zgv...38ahSrBFEVnxjpnPh1Q1c", + "dp": "tzDGjECFOU0ehqtuqhcu...dVGAXJoGOdv5VpaZ7B1QE", + "dq": "kh5dyDk7YCz7sUFbpsmu...aX9PKa12HFlny6K1daL48", + "qi": "AlHWbx1gp6Z9pbw_1hlS...lhmIOgRApS0t9VoXtHhFU" +} +``` + +## JWK-to-PEM + +* [x] PKCS#1 (traditional) +* [x] PKCS#8, SPKI/PKIX +* [x] 2048-bit, 4096-bit (and ostensibily all others) +* [x] SSH (RFC4716), (RFC 4716/SSH2) + +```js +var Rasha = require('rasha'); +var jwk = require('rasha/fixtures/privkey-rsa-2048.jwk.json'); + +Rasha.export({ jwk: jwk }).then(function (pem) { + // PEM in PKCS1 (traditional) format + console.log(pem); +}); +``` + +``` +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAm2ttVBxPlWw06ZmGBWVDlfjkPAJ4DgnY0TrDwtCohHzLxGhD +NzUJefLukC+xu0LBKylYojT5vTkxaOhxeSYo31syu4WhxbkTBLICOFcCGMob6pSQ +38P8LdAIlb0pqDHxEJ9adWomjuFf.....5cCBahfsiNtNR6WV1/iCSuINYs6uPdA +Jlw7hm9m8TAmFWWyfL0s7wiRvAYkQvpxetorTwHJVLabBDJ+WBOAY2enOLHIRQv+ +atAvHrLXjkUdzF96o0icyF6n7QzGfUPmeWGYg6BEClLS31Whe0eEVQ== +-----END RSA PRIVATE KEY----- +``` + +### Advanced Options + +`format: 'pkcs8'`: + +The default output format `pkcs1` (RSA-specific format) is used for private keys. +Use `format: 'pkcs8'` to output in PKCS#8 format instead. + +```js +Rasha.export({ jwk: jwk, format: 'pkcs8' }).then(function (pem) { + // PEM in PKCS#8 format + console.log(pem); +}); +``` + +``` +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCba21UHE+VbDTp +mYYFZUOV+OQ8AngOCdjROsPC0KiEfMvEaEM3NQl58u6QL7G7QsErKViiNPm9OTFo +6HF5JijfWzK7haHFuRMEsgI4VwIY.....LorV1ovjwKBgAJR1m8dYKemfaW8P9YZ +Uux7lwIFqF+yI201HpZXX+IJK4g1izq490AmXDuGb2bxMCYVZbJ8vSzvCJG8BiRC ++nF62itPAclUtpsEMn5YE4BjZ6c4schFC/5q0C8esteORR3MX3qjSJzIXqftDMZ9 +Q+Z5YZiDoEQKUtLfVaF7R4RV +-----END PRIVATE KEY----- +``` + +`format: 'ssh'`: + +Although SSH uses PKCS#1 for private keys, it uses ts own special non-ASN1 format +(affectionately known as rfc4716) for public keys. I got curious and then decided +to add this format as well. + +To get the same format as you +would get with `ssh-keygen`, pass `ssh` as the format option: + +```js +Rasha.export({ jwk: jwk, format: 'ssh' }).then(function (pub) { + // Special SSH2 Public Key format (RFC 4716) + console.log(pub); +}); +``` + +``` +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCba21UHE.....Q02P1Eamz/nT4I3 rsa@localhost +``` + +`public: 'true'`: + +If a private key is used as input, a private key will be output. + +If you'd like to output a public key instead you can pass `public: true`. + +or `format: 'spki'`. + +```js +Rasha.export({ jwk: jwk, public: true }).then(function (pem) { + // PEM in SPKI/PKIX format + console.log(pem); +}); +``` + +``` +-----BEGIN PUBLIC KEY----- +MIIBCgKCAQEAm2ttVBxPlWw06ZmGBWVDlfjkPAJ4DgnY0TrDwtCohHzLxGhDNzUJ +efLukC+xu0LBKylYojT5vTkxaOhx.....TmzCh2ikrwTMja7mUdBJf2bK3By5AB0 +Qi49OykUCfNZeQlEz7UNNj9RGps/50+CNwIDAQAB +-----END PUBLIC KEY----- +``` + +Testing +------- + +All cases are tested in `test.sh`. + +You can compare these keys to the ones that you get from OpenSSL, OpenSSH/ssh-keygen, and WebCrypto: + +```bash +# Generate 2048-bit RSA Keypair +openssl genrsa -out privkey-rsa-2048.pkcs1.pem 2048 + +# Convert PKCS1 (traditional) RSA Keypair to PKCS8 format +openssl rsa -in privkey-rsa-2048.pkcs1.pem -pubout -out pub-rsa-2048.spki.pem + +# Export Public-only RSA Key in PKCS1 (traditional) format +openssl pkcs8 -topk8 -nocrypt -in privkey-rsa-2048.pkcs1.pem -out privkey-rsa-2048.pkcs8.pem + +# Convert PKCS1 (traditional) RSA Public Key to SPKI/PKIX format +openssl rsa -in pub-rsa-2048.spki.pem -pubin -RSAPublicKey_out -out pub-rsa-2048.pkcs1.pem + +# Convert RSA public key to SSH format +ssh-keygen -f ./pub-rsa-2048.spki.pem -i -mPKCS8 > ./pub-rsa-2048.ssh.pub +``` + +Goals of this project +----- + +* Focused support for 2048-bit and 4096-bit RSA keypairs (although any size is technically supported) +* Zero Dependencies +* VanillaJS +* Quality Code: Good comments and tests +* Convert both ways: PEM-to-JWK and JWK-to-PEM (also supports SSH pub files) +* Browser support as well (TODO) +* OpenSSL, ssh-keygen, and WebCrypto compatibility + +Legal +----- + +[Rasha.js](https://git.coolaj86.com/coolaj86/rasha.js) | +MPL-2.0 | +[Terms of Use](https://therootcompany.com/legal/#terms) | +[Privacy Policy](https://therootcompany.com/legal/#privacy) diff --git a/express-server/node_modules/rsa-compat/lib/rasha/bin/rasha.js b/express-server/node_modules/rsa-compat/lib/rasha/bin/rasha.js new file mode 100644 index 00000000..4ffed3c5 --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rasha/bin/rasha.js @@ -0,0 +1,97 @@ +#!/usr/bin/env node +'use strict'; + +var fs = require('fs'); +var Rasha = require('../index.js'); +var PEM = require('../lib/pem.js'); +var ASN1 = require('../lib/asn1.js'); + +var infile = process.argv[2]; +var format = process.argv[3]; +var msg = process.argv[4]; +var sign; +if ('sign' === format) { + sign = true; + format = 'pkcs8'; +} + +if (!infile) { + infile = 'jwk'; +} + +if (-1 !== [ 'jwk', 'pem', 'json', 'der', 'pkcs1', 'pkcs8', 'spki' ].indexOf(infile)) { + console.log("Generating new key..."); + Rasha.generate({ + format: infile + , modulusLength: parseInt(format, 10) || 2048 + , encoding: parseInt(format, 10) ? null : format + }).then(function (key) { + if ('der' === infile || 'der' === format) { + key.private = key.private.toString('binary'); + key.public = key.public.toString('binary'); + } + console.log(key.private); + console.log(key.public); + }).catch(function (err) { + console.error(err); + process.exit(1); + }); + return; +} +var key = fs.readFileSync(infile, 'ascii'); + +try { + key = JSON.parse(key); +} catch(e) { + // ignore +} + +if ('string' === typeof key) { + if ('tpl' === format) { + var block = PEM.parseBlock(key); + var asn1 = ASN1.parse(block.der); + ASN1.tpl(asn1); + return; + } + if (sign) { signMessage(key, msg); return; } + + var pub = (-1 !== [ 'public', 'spki', 'pkix' ].indexOf(format)); + Rasha.import({ pem: key, public: (pub || format) }).then(function (jwk) { + console.info(JSON.stringify(jwk, null, 2)); + }).catch(function (err) { + console.error(err); + process.exit(1); + }); +} else { + Rasha.export({ jwk: key, format: format }).then(function (pem) { + if (sign) { signMessage(pem, msg); return; } + console.info(pem); + }).catch(function (err) { + console.error(err); + process.exit(2); + }); +} + +function signMessage(pem, name) { + var msg; + try { + msg = fs.readFileSync(name); + } catch(e) { + console.warn("[info] input string did not exist as a file, signing the string itself"); + msg = Buffer.from(name, 'binary'); + } + var crypto = require('crypto'); + var sign = crypto.createSign('SHA256'); + sign.write(msg) + sign.end() + var buf = sign.sign(pem, 'hex'); + console.log(buf); + //console.log(buf.toString('base64')); + /* + Rasha.sign({ pem: pem, message: msg, alg: 'SHA256' }).then(function (sig) { + }).catch(function () { + console.error(err); + process.exit(3); + }); + */ +} diff --git a/express-server/node_modules/rsa-compat/lib/rasha/fixtures/privkey-rsa-2048.jwk.json b/express-server/node_modules/rsa-compat/lib/rasha/fixtures/privkey-rsa-2048.jwk.json new file mode 100644 index 00000000..f344c22f --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rasha/fixtures/privkey-rsa-2048.jwk.json @@ -0,0 +1,11 @@ +{ + "kty": "RSA", + "n": "m2ttVBxPlWw06ZmGBWVDlfjkPAJ4DgnY0TrDwtCohHzLxGhDNzUJefLukC-xu0LBKylYojT5vTkxaOhxeSYo31syu4WhxbkTBLICOFcCGMob6pSQ38P8LdAIlb0pqDHxEJ9adWomjuFf0SUhN1cP7s9m8Yk9trkpEqjskocn2BOnTB57qAZM6-I70on0_iDZm7-jcqOPgADAmbWHhy67BXkk4yy_YzD4yOGZFXZcNp915_TW5bRd__AKPHUHxJasPiyEFqlNKBR2DSD-LbX5eTmzCh2ikrwTMja7mUdBJf2bK3By5AB0Qi49OykUCfNZeQlEz7UNNj9RGps_50-CNw", + "e": "AQAB", + "d": "Cpfo7Mm9Nu8YMC_xrZ54W9mKHPkCG9rZ93Ds9PNp-RXUgb-ljTbFPZWsYxGNKLllFz8LNosr1pT2ZDMrwNk0Af1iWNvD6gkyXaiQdCyiDPSBsJyNv2LJZon-e85X74nv53UlIkmo9SYxdLz2JaJ-iIWEe8Qh-7llLktrTJV_xr98_tbhgSppz_IeOymq3SEZaQHM8pTU7w7XvCj2pb9r8fN0M0XcgWZIaf3LGEfkhF_WtX67XJ0C6-LbkT51jtlLRNGX6haGdscXS0OWWjKOJzKGuV-NbthEn5rmRtVnjRZ3yaxQ0ud8vC-NONn7yvGUlOur1IdDzJ_YfHPt9sHMQQ", + "p": "ynG-t9HwKCN3MWRYFdnFzi9-02Qcy3p8B5pu3ary2E70hYn2pHlUG2a9BNE8c5xHQ3Hx43WoWf6s0zOunPV1G28LkU_UYEbAtPv_PxSmzpQp9n9XnYvBLBF8Y3z7gxgLn1vVFNARrQdRtj87qY3aw7E9S4DsGcAarIuOT2TsTCE", + "q": "xIkAjgUzB1zaUzJtW2Zgvp9cYYr1DmpH30ePZl3c_8397_DZDDo46fnFYjs6uPa03HpmKUnbjwr14QHlfXlntJBEuXxcqLjkdKdJ4ob7xueLTK4suo9V8LSrkLChVxlZQwnFD2E5ll0sVeeDeMJHQw38ahSrBFEVnxjpnPh1Q1c", + "dp": "tzDGjECFOU0ehqtuqhcuT63a7h8hj19-7MJqoFwY9HQ-ALkfXyYLXeBSGxHbyiIYuodZg6LsfMNgUJ3r3Eyhc_nAVfYPEC_2IdAG4WYmq7iXYF9LQV09qEsKbFykm7QekE3hO7wswo5k-q2tp3ieBYdVGAXJoGOdv5VpaZ7B1QE", + "dq": "kh5dyDk7YCz7sUFbpsmuAeuPjoH2ghooh2u3xN7iUVmAg-ToKjwbVnG5-7eXiC779rQVwnrD_0yh1AFJ8wjRPqDIR7ObXGHikIxT1VSQWqiJm6AfZzDsL0LUD4YS3iPdhob7-NxLKWzqao_u4lhnDQaX9PKa12HFlny6K1daL48", + "qi": "AlHWbx1gp6Z9pbw_1hlS7HuXAgWoX7IjbTUelldf4gkriDWLOrj3QCZcO4ZvZvEwJhVlsny9LO8IkbwGJEL6cXraK08ByVS2mwQyflgTgGNnpzixyEUL_mrQLx6y145FHcxfeqNInMhep-0Mxn1D5nlhmIOgRApS0t9VoXtHhFU" +} diff --git a/express-server/node_modules/rsa-compat/lib/rasha/fixtures/privkey-rsa-2048.pkcs1.pem b/express-server/node_modules/rsa-compat/lib/rasha/fixtures/privkey-rsa-2048.pkcs1.pem new file mode 100644 index 00000000..246bd35c --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rasha/fixtures/privkey-rsa-2048.pkcs1.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAm2ttVBxPlWw06ZmGBWVDlfjkPAJ4DgnY0TrDwtCohHzLxGhD +NzUJefLukC+xu0LBKylYojT5vTkxaOhxeSYo31syu4WhxbkTBLICOFcCGMob6pSQ +38P8LdAIlb0pqDHxEJ9adWomjuFf0SUhN1cP7s9m8Yk9trkpEqjskocn2BOnTB57 +qAZM6+I70on0/iDZm7+jcqOPgADAmbWHhy67BXkk4yy/YzD4yOGZFXZcNp915/TW +5bRd//AKPHUHxJasPiyEFqlNKBR2DSD+LbX5eTmzCh2ikrwTMja7mUdBJf2bK3By +5AB0Qi49OykUCfNZeQlEz7UNNj9RGps/50+CNwIDAQABAoIBAAqX6OzJvTbvGDAv +8a2eeFvZihz5Ahva2fdw7PTzafkV1IG/pY02xT2VrGMRjSi5ZRc/CzaLK9aU9mQz +K8DZNAH9Yljbw+oJMl2okHQsogz0gbCcjb9iyWaJ/nvOV++J7+d1JSJJqPUmMXS8 +9iWifoiFhHvEIfu5ZS5La0yVf8a/fP7W4YEqac/yHjspqt0hGWkBzPKU1O8O17wo +9qW/a/HzdDNF3IFmSGn9yxhH5IRf1rV+u1ydAuvi25E+dY7ZS0TRl+oWhnbHF0tD +lloyjicyhrlfjW7YRJ+a5kbVZ40Wd8msUNLnfLwvjTjZ+8rxlJTrq9SHQ8yf2Hxz +7fbBzEECgYEAynG+t9HwKCN3MWRYFdnFzi9+02Qcy3p8B5pu3ary2E70hYn2pHlU +G2a9BNE8c5xHQ3Hx43WoWf6s0zOunPV1G28LkU/UYEbAtPv/PxSmzpQp9n9XnYvB +LBF8Y3z7gxgLn1vVFNARrQdRtj87qY3aw7E9S4DsGcAarIuOT2TsTCECgYEAxIkA +jgUzB1zaUzJtW2Zgvp9cYYr1DmpH30ePZl3c/8397/DZDDo46fnFYjs6uPa03Hpm +KUnbjwr14QHlfXlntJBEuXxcqLjkdKdJ4ob7xueLTK4suo9V8LSrkLChVxlZQwnF +D2E5ll0sVeeDeMJHQw38ahSrBFEVnxjpnPh1Q1cCgYEAtzDGjECFOU0ehqtuqhcu +T63a7h8hj19+7MJqoFwY9HQ+ALkfXyYLXeBSGxHbyiIYuodZg6LsfMNgUJ3r3Eyh +c/nAVfYPEC/2IdAG4WYmq7iXYF9LQV09qEsKbFykm7QekE3hO7wswo5k+q2tp3ie +BYdVGAXJoGOdv5VpaZ7B1QECgYEAkh5dyDk7YCz7sUFbpsmuAeuPjoH2ghooh2u3 +xN7iUVmAg+ToKjwbVnG5+7eXiC779rQVwnrD/0yh1AFJ8wjRPqDIR7ObXGHikIxT +1VSQWqiJm6AfZzDsL0LUD4YS3iPdhob7+NxLKWzqao/u4lhnDQaX9PKa12HFlny6 +K1daL48CgYACUdZvHWCnpn2lvD/WGVLse5cCBahfsiNtNR6WV1/iCSuINYs6uPdA +Jlw7hm9m8TAmFWWyfL0s7wiRvAYkQvpxetorTwHJVLabBDJ+WBOAY2enOLHIRQv+ +atAvHrLXjkUdzF96o0icyF6n7QzGfUPmeWGYg6BEClLS31Whe0eEVQ== +-----END RSA PRIVATE KEY----- diff --git a/express-server/node_modules/rsa-compat/lib/rasha/fixtures/privkey-rsa-2048.pkcs8.pem b/express-server/node_modules/rsa-compat/lib/rasha/fixtures/privkey-rsa-2048.pkcs8.pem new file mode 100644 index 00000000..53dbf837 --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rasha/fixtures/privkey-rsa-2048.pkcs8.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCba21UHE+VbDTp +mYYFZUOV+OQ8AngOCdjROsPC0KiEfMvEaEM3NQl58u6QL7G7QsErKViiNPm9OTFo +6HF5JijfWzK7haHFuRMEsgI4VwIYyhvqlJDfw/wt0AiVvSmoMfEQn1p1aiaO4V/R +JSE3Vw/uz2bxiT22uSkSqOyShyfYE6dMHnuoBkzr4jvSifT+INmbv6Nyo4+AAMCZ +tYeHLrsFeSTjLL9jMPjI4ZkVdlw2n3Xn9NbltF3/8Ao8dQfElqw+LIQWqU0oFHYN +IP4ttfl5ObMKHaKSvBMyNruZR0El/ZsrcHLkAHRCLj07KRQJ81l5CUTPtQ02P1Ea +mz/nT4I3AgMBAAECggEACpfo7Mm9Nu8YMC/xrZ54W9mKHPkCG9rZ93Ds9PNp+RXU +gb+ljTbFPZWsYxGNKLllFz8LNosr1pT2ZDMrwNk0Af1iWNvD6gkyXaiQdCyiDPSB +sJyNv2LJZon+e85X74nv53UlIkmo9SYxdLz2JaJ+iIWEe8Qh+7llLktrTJV/xr98 +/tbhgSppz/IeOymq3SEZaQHM8pTU7w7XvCj2pb9r8fN0M0XcgWZIaf3LGEfkhF/W +tX67XJ0C6+LbkT51jtlLRNGX6haGdscXS0OWWjKOJzKGuV+NbthEn5rmRtVnjRZ3 +yaxQ0ud8vC+NONn7yvGUlOur1IdDzJ/YfHPt9sHMQQKBgQDKcb630fAoI3cxZFgV +2cXOL37TZBzLenwHmm7dqvLYTvSFifakeVQbZr0E0TxznEdDcfHjdahZ/qzTM66c +9XUbbwuRT9RgRsC0+/8/FKbOlCn2f1edi8EsEXxjfPuDGAufW9UU0BGtB1G2Pzup +jdrDsT1LgOwZwBqsi45PZOxMIQKBgQDEiQCOBTMHXNpTMm1bZmC+n1xhivUOakff +R49mXdz/zf3v8NkMOjjp+cViOzq49rTcemYpSduPCvXhAeV9eWe0kES5fFyouOR0 +p0nihvvG54tMriy6j1XwtKuQsKFXGVlDCcUPYTmWXSxV54N4wkdDDfxqFKsEURWf +GOmc+HVDVwKBgQC3MMaMQIU5TR6Gq26qFy5PrdruHyGPX37swmqgXBj0dD4AuR9f +Jgtd4FIbEdvKIhi6h1mDoux8w2BQnevcTKFz+cBV9g8QL/Yh0AbhZiaruJdgX0tB +XT2oSwpsXKSbtB6QTeE7vCzCjmT6ra2neJ4Fh1UYBcmgY52/lWlpnsHVAQKBgQCS +Hl3IOTtgLPuxQVumya4B64+OgfaCGiiHa7fE3uJRWYCD5OgqPBtWcbn7t5eILvv2 +tBXCesP/TKHUAUnzCNE+oMhHs5tcYeKQjFPVVJBaqImboB9nMOwvQtQPhhLeI92G +hvv43EspbOpqj+7iWGcNBpf08prXYcWWfLorV1ovjwKBgAJR1m8dYKemfaW8P9YZ +Uux7lwIFqF+yI201HpZXX+IJK4g1izq490AmXDuGb2bxMCYVZbJ8vSzvCJG8BiRC ++nF62itPAclUtpsEMn5YE4BjZ6c4schFC/5q0C8esteORR3MX3qjSJzIXqftDMZ9 +Q+Z5YZiDoEQKUtLfVaF7R4RV +-----END PRIVATE KEY----- diff --git a/express-server/node_modules/rsa-compat/lib/rasha/fixtures/pub-rsa-2048.jwk.json b/express-server/node_modules/rsa-compat/lib/rasha/fixtures/pub-rsa-2048.jwk.json new file mode 100644 index 00000000..333b300e --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rasha/fixtures/pub-rsa-2048.jwk.json @@ -0,0 +1,5 @@ +{ + "kty": "RSA", + "n": "m2ttVBxPlWw06ZmGBWVDlfjkPAJ4DgnY0TrDwtCohHzLxGhDNzUJefLukC-xu0LBKylYojT5vTkxaOhxeSYo31syu4WhxbkTBLICOFcCGMob6pSQ38P8LdAIlb0pqDHxEJ9adWomjuFf0SUhN1cP7s9m8Yk9trkpEqjskocn2BOnTB57qAZM6-I70on0_iDZm7-jcqOPgADAmbWHhy67BXkk4yy_YzD4yOGZFXZcNp915_TW5bRd__AKPHUHxJasPiyEFqlNKBR2DSD-LbX5eTmzCh2ikrwTMja7mUdBJf2bK3By5AB0Qi49OykUCfNZeQlEz7UNNj9RGps_50-CNw", + "e": "AQAB" +} diff --git a/express-server/node_modules/rsa-compat/lib/rasha/fixtures/pub-rsa-2048.pkcs1.pem b/express-server/node_modules/rsa-compat/lib/rasha/fixtures/pub-rsa-2048.pkcs1.pem new file mode 100644 index 00000000..e592fdad --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rasha/fixtures/pub-rsa-2048.pkcs1.pem @@ -0,0 +1,8 @@ +-----BEGIN RSA PUBLIC KEY----- +MIIBCgKCAQEAm2ttVBxPlWw06ZmGBWVDlfjkPAJ4DgnY0TrDwtCohHzLxGhDNzUJ +efLukC+xu0LBKylYojT5vTkxaOhxeSYo31syu4WhxbkTBLICOFcCGMob6pSQ38P8 +LdAIlb0pqDHxEJ9adWomjuFf0SUhN1cP7s9m8Yk9trkpEqjskocn2BOnTB57qAZM +6+I70on0/iDZm7+jcqOPgADAmbWHhy67BXkk4yy/YzD4yOGZFXZcNp915/TW5bRd +//AKPHUHxJasPiyEFqlNKBR2DSD+LbX5eTmzCh2ikrwTMja7mUdBJf2bK3By5AB0 +Qi49OykUCfNZeQlEz7UNNj9RGps/50+CNwIDAQAB +-----END RSA PUBLIC KEY----- diff --git a/express-server/node_modules/rsa-compat/lib/rasha/fixtures/pub-rsa-2048.spki.pem b/express-server/node_modules/rsa-compat/lib/rasha/fixtures/pub-rsa-2048.spki.pem new file mode 100644 index 00000000..465d1155 --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rasha/fixtures/pub-rsa-2048.spki.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm2ttVBxPlWw06ZmGBWVD +lfjkPAJ4DgnY0TrDwtCohHzLxGhDNzUJefLukC+xu0LBKylYojT5vTkxaOhxeSYo +31syu4WhxbkTBLICOFcCGMob6pSQ38P8LdAIlb0pqDHxEJ9adWomjuFf0SUhN1cP +7s9m8Yk9trkpEqjskocn2BOnTB57qAZM6+I70on0/iDZm7+jcqOPgADAmbWHhy67 +BXkk4yy/YzD4yOGZFXZcNp915/TW5bRd//AKPHUHxJasPiyEFqlNKBR2DSD+LbX5 +eTmzCh2ikrwTMja7mUdBJf2bK3By5AB0Qi49OykUCfNZeQlEz7UNNj9RGps/50+C +NwIDAQAB +-----END PUBLIC KEY----- diff --git a/express-server/node_modules/rsa-compat/lib/rasha/fixtures/pub-rsa-2048.ssh.pub b/express-server/node_modules/rsa-compat/lib/rasha/fixtures/pub-rsa-2048.ssh.pub new file mode 100644 index 00000000..a00fd4cb --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rasha/fixtures/pub-rsa-2048.ssh.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCba21UHE+VbDTpmYYFZUOV+OQ8AngOCdjROsPC0KiEfMvEaEM3NQl58u6QL7G7QsErKViiNPm9OTFo6HF5JijfWzK7haHFuRMEsgI4VwIYyhvqlJDfw/wt0AiVvSmoMfEQn1p1aiaO4V/RJSE3Vw/uz2bxiT22uSkSqOyShyfYE6dMHnuoBkzr4jvSifT+INmbv6Nyo4+AAMCZtYeHLrsFeSTjLL9jMPjI4ZkVdlw2n3Xn9NbltF3/8Ao8dQfElqw+LIQWqU0oFHYNIP4ttfl5ObMKHaKSvBMyNruZR0El/ZsrcHLkAHRCLj07KRQJ81l5CUTPtQ02P1Eamz/nT4I3 rsa@localhost diff --git a/express-server/node_modules/rsa-compat/lib/rasha/index.js b/express-server/node_modules/rsa-compat/lib/rasha/index.js new file mode 100644 index 00000000..c538483e --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rasha/index.js @@ -0,0 +1,2 @@ +'use strict'; +module.exports = require('./lib/rasha.js'); diff --git a/express-server/node_modules/rsa-compat/lib/rasha/lib/asn1.js b/express-server/node_modules/rsa-compat/lib/rasha/lib/asn1.js new file mode 100644 index 00000000..bce9568b --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rasha/lib/asn1.js @@ -0,0 +1,235 @@ +'use strict'; + +// +// A dumbed-down, minimal ASN.1 parser / packer combo +// +// Note: generally I like to write congruent code +// (i.e. output can be used as input and vice-versa) +// However, this seemed to be more readable and easier +// to use written as-is, asymmetrically. +// (I also generally prefer to export objects rather +// functions but, yet again, asthetics one in this case) + +var Enc = require('./encoding.js'); + +// +// Packer +// + +// Almost every ASN.1 type that's important for CSR +// can be represented generically with only a few rules. +var ASN1 = module.exports = function ASN1(/*type, hexstrings...*/) { + var args = Array.prototype.slice.call(arguments); + var typ = args.shift(); + var str = args.join('').replace(/\s+/g, '').toLowerCase(); + var len = (str.length/2); + var lenlen = 0; + var hex = typ; + + // We can't have an odd number of hex chars + if (len !== Math.round(len)) { + throw new Error("invalid hex"); + } + + // The first byte of any ASN.1 sequence is the type (Sequence, Integer, etc) + // The second byte is either the size of the value, or the size of its size + + // 1. If the second byte is < 0x80 (128) it is considered the size + // 2. If it is > 0x80 then it describes the number of bytes of the size + // ex: 0x82 means the next 2 bytes describe the size of the value + // 3. The special case of exactly 0x80 is "indefinite" length (to end-of-file) + + if (len > 127) { + lenlen += 1; + while (len > 255) { + lenlen += 1; + len = len >> 8; + } + } + + if (lenlen) { hex += Enc.numToHex(0x80 + lenlen); } + return hex + Enc.numToHex(str.length/2) + str; +}; + +// The Integer type has some special rules +ASN1.UInt = function UINT() { + var str = Array.prototype.slice.call(arguments).join(''); + var first = parseInt(str.slice(0, 2), 16); + + // If the first byte is 0x80 or greater, the number is considered negative + // Therefore we add a '00' prefix if the 0x80 bit is set + if (0x80 & first) { str = '00' + str; } + + return ASN1('02', str); +}; + +// The Bit String type also has a special rule +ASN1.BitStr = function BITSTR() { + var str = Array.prototype.slice.call(arguments).join(''); + // '00' is a mask of how many bits of the next byte to ignore + return ASN1('03', '00' + str); +}; + + +// +// Parser +// + +ASN1.ELOOP = "uASN1.js Error: iterated over 15+ elements (probably a malformed file)"; +ASN1.EDEEP = "uASN1.js Error: element nested 20+ layers deep (probably a malformed file)"; +// Container Types are Sequence 0x30, Octect String 0x04, Array? (0xA0, 0xA1) +// Value Types are Integer 0x02, Bit String 0x03, Null 0x05, Object ID 0x06, +// Sometimes Bit String is used as a container (RSA Pub Spki) +ASN1.VTYPES = [ 0x02, 0x03, 0x05, 0x06, 0x0c, 0x82 ]; +ASN1.parse = function parseAsn1(buf, depth, ws) { + if (!ws) { ws = ''; } + if (depth >= 20) { throw new Error(ASN1.EDEEP); } + + var index = 2; // we know, at minimum, data starts after type (0) and lengthSize (1) + var asn1 = { type: buf[0], lengthSize: 0, length: buf[1] }; + var child; + var iters = 0; + var adjust = 0; + var adjustedLen; + + // Determine how many bytes the length uses, and what it is + if (0x80 & asn1.length) { + asn1.lengthSize = 0x7f & asn1.length; + // I think that buf->hex->int solves the problem of Endianness... not sure + asn1.length = parseInt(Enc.bufToHex(buf.slice(index, index + asn1.lengthSize)), 16); + index += asn1.lengthSize; + } + + // High-order bit Integers have a leading 0x00 to signify that they are positive. + // Bit Streams use the first byte to signify padding, which x.509 doesn't use. + if (0x00 === buf[index] && (0x02 === asn1.type || 0x03 === asn1.type)) { + // However, 0x00 on its own is a valid number + if (asn1.length > 1) { + index += 1; + adjust = -1; + } + } + adjustedLen = asn1.length + adjust; + + //console.warn(ws + '0x' + Enc.numToHex(asn1.type), index, 'len:', asn1.length, asn1); + + // this is a primitive value type + if (-1 !== ASN1.VTYPES.indexOf(asn1.type)) { + asn1.value = buf.slice(index, index + adjustedLen); + return asn1; + } + + asn1.children = []; + //console.warn('1 len:', (2 + asn1.lengthSize + asn1.length), 'idx:', index, 'clen:', 0); + while (iters < 15 && index < (2 + asn1.length + asn1.lengthSize)) { + iters += 1; + child = ASN1.parse(buf.slice(index, index + adjustedLen), (depth || 0) + 1, ws + ' '); + // The numbers don't match up exactly and I don't remember why... + // probably something with adjustedLen or some such, but the tests pass + index += (2 + child.lengthSize + child.length); + //console.warn('2 len:', (2 + asn1.lengthSize + asn1.length), 'idx:', index, 'clen:', (2 + child.lengthSize + child.length)); + if (index > (2 + asn1.lengthSize + asn1.length)) { + console.error(JSON.stringify(asn1, function (k, v) { + if ('value' === k) { return '0x' + Enc.bufToHex(v.data); } return v; + }, 2)); + throw new Error("Parse error: child value length (" + child.length + + ") is greater than remaining parent length (" + (asn1.length - index) + + " = " + asn1.length + " - " + index + ")"); + } + asn1.children.push(child); + //console.warn(ws + '0x' + Enc.numToHex(asn1.type), index, 'len:', asn1.length, asn1); + } + if (index !== (2 + asn1.lengthSize + asn1.length)) { + console.warn('index:', index, 'length:', (2 + asn1.lengthSize + asn1.length)) + throw new Error("premature end-of-file"); + } + if (iters >= 15) { throw new Error(ASN1.ELOOP); } + + return asn1; +}; + +/* +ASN1._stringify = function(asn1) { + //console.log(JSON.stringify(asn1, null, 2)); + //console.log(asn1); + var ws = ''; + + function write(asn1) { + console.log(ws, 'ch', Enc.numToHex(asn1.type), asn1.length); + if (!asn1.children) { + return; + } + asn1.children.forEach(function (a) { + ws += '\t'; + write(a); + ws = ws.slice(1); + }); + } + write(asn1); +}; +*/ + +ASN1.tpl = function (asn1) { + //console.log(JSON.stringify(asn1, null, 2)); + //console.log(asn1); + var sp = ' '; + var ws = sp; + var i = 0; + var vars = []; + var str = ws; + + function write(asn1, k) { + str += "\n" + ws; + var val; + if ('number' !== typeof k) { + // ignore + } else { + str += ', '; + } + if (0x02 === asn1.type) { + str += "ASN1.UInt("; + } else if (0x03 === asn1.type) { + str += "ASN1.BitStr("; + } else { + str += "ASN1('" + Enc.numToHex(asn1.type) + "'"; + } + if (!asn1.children) { + if (0x05 !== asn1.type) { + if (0x06 !== asn1.type) { + val = asn1.value || new Uint8Array(0); + vars.push("\n// 0x" + Enc.numToHex(val.byteLength) + " (" + val.byteLength + " bytes)\nopts.tpl" + i + " = '" + + Enc.bufToHex(val) + "';"); + if (0x02 !== asn1.type && 0x03 !== asn1.type) { + str += ", "; + } + str += "Enc.bufToHex(opts.tpl" + i + ")"; + } else { + str += ", '" + Enc.bufToHex(asn1.value) + "'"; + } + } else { + console.warn("XXXXXXXXXXXXXXXXXXXXX"); + } + str += ")"; + return ; + } + asn1.children.forEach(function (a, j) { + i += 1; + ws += sp; + write(a, j); + ws = ws.slice(sp.length); + }); + str += "\n" + ws + ")"; + } + + write(asn1); + console.log('var opts = {};'); + console.log(vars.join('\n') + '\n'); + console.log(); + console.log('function buildSchema(opts) {'); + console.log(sp + 'return Enc.hexToBuf(' + str.slice(3) + ');'); + console.log('}'); + console.log(); + console.log('buildSchema(opts);'); +}; + +module.exports = ASN1; diff --git a/express-server/node_modules/rsa-compat/lib/rasha/lib/encoding.js b/express-server/node_modules/rsa-compat/lib/rasha/lib/encoding.js new file mode 100644 index 00000000..7ed4116d --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rasha/lib/encoding.js @@ -0,0 +1,104 @@ +'use strict'; + +var Enc = module.exports; + +Enc.base64ToBuf = function (str) { + // always convert from urlsafe base64, just in case + //return Buffer.from(Enc.urlBase64ToBase64(str)).toString('base64'); + // node handles urlBase64 automatically + return Buffer.from(str, 'base64'); +}; + +Enc.base64ToHex = function (b64) { + return Enc.bufToHex(Enc.base64ToBuf(b64)); +}; + +Enc.bufToBase64 = function (u8) { + // we want to maintain api compatability with browser APIs, + // so we assume that this could be a Uint8Array + return Buffer.from(u8).toString('base64'); +}; + +/* +Enc.bufToUint8 = function bufToUint8(buf) { + return new Uint8Array(buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength)); +}; +*/ + +Enc.bufToUrlBase64 = function (u8) { + return Enc.bufToBase64(u8) + .replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, ''); +}; + + +Enc.bufToHex = function (u8) { + var hex = []; + var i, h; + var len = (u8.byteLength || u8.length); + + for (i = 0; i < len; i += 1) { + h = u8[i].toString(16); + if (2 !== h.length) { h = '0' + h; } + hex.push(h); + } + + return hex.join('').toLowerCase(); +}; + +Enc.hexToBase64 = function (hex) { + return Buffer.from(hex, 'hex').toString('base64'); +}; + +Enc.hexToBuf = function (hex) { + return Buffer.from(hex, 'hex'); +}; + +Enc.numToHex = function (d) { + d = d.toString(16); + if (d.length % 2) { + return '0' + d; + } + return d; +}; + +/* +Enc.strToBase64 = function (str) { + // node automatically can tell the difference + // between uc2 (utf-8) strings and binary strings + // so we don't have to re-encode the strings + return Buffer.from(str).toString('base64'); +}; +*/ + +/* +Enc.strToBin = function (str) { + var escstr = encodeURIComponent(str); + // replaces any uri escape sequence, such as %0A, + // with binary escape, such as 0x0A + var binstr = escstr.replace(/%([0-9A-F]{2})/g, function(match, p1) { + return String.fromCharCode(parseInt(p1, 16)); + }); + + return binstr; +}; +*/ + +Enc.strToBuf = function (str) { + return Buffer.from(str); +}; + +Enc.strToHex = function (str) { + return Buffer.from(str).toString('hex'); +}; + +/* +Enc.urlBase64ToBase64 = function (str) { + var r = str % 4; + if (2 === r) { + str += '=='; + } else if (3 === r) { + str += '='; + } + return str.replace(/-/g, '+').replace(/_/g, '/'); +}; +*/ diff --git a/express-server/node_modules/rsa-compat/lib/rasha/lib/pem.js b/express-server/node_modules/rsa-compat/lib/rasha/lib/pem.js new file mode 100644 index 00000000..76aec964 --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rasha/lib/pem.js @@ -0,0 +1,28 @@ +'use strict'; + +var PEM = module.exports; +var Enc = require('./encoding.js'); + +PEM.parseBlock = function pemToDer(pem) { + var lines = pem.trim().split(/\n/); + var end = lines.length - 1; + var head = lines[0].match(/-----BEGIN (.*)-----/); + var foot = lines[end].match(/-----END (.*)-----/); + + if (head) { + lines = lines.slice(1, end); + head = head[1]; + if (head !== foot[1]) { + throw new Error("headers and footers do not match"); + } + } + + return { type: head, bytes: Enc.base64ToBuf(lines.join('')) }; +}; + +PEM.packBlock = function (opts) { + return '-----BEGIN ' + opts.type + '-----\n' + + Enc.bufToBase64(opts.bytes).match(/.{1,64}/g).join('\n') + '\n' + + '-----END ' + opts.type + '-----' + ; +}; diff --git a/express-server/node_modules/rsa-compat/lib/rasha/lib/rasha.js b/express-server/node_modules/rsa-compat/lib/rasha/lib/rasha.js new file mode 100644 index 00000000..67d1d0b4 --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rasha/lib/rasha.js @@ -0,0 +1,204 @@ +'use strict'; + +var RSA = module.exports; +var SSH = require('./ssh.js'); +var PEM = require('./pem.js'); +var x509 = require('./x509.js'); +var ASN1 = require('./asn1.js'); + +/*global Promise*/ +RSA.generate = function (opts) { + return Promise.resolve().then(function () { + var typ = 'rsa'; + var format = opts.format; + var encoding = opts.encoding; + var priv; + var pub; + + if (!format) { + format = 'jwk'; + } + if ('spki' === format || 'pkcs8' === format) { + format = 'pkcs8'; + pub = 'spki'; + } + + if ('pem' === format) { + format = 'pkcs1'; + encoding = 'pem'; + } else if ('der' === format) { + format = 'pkcs1'; + encoding = 'der'; + } + + if ('jwk' === format || 'json' === format) { + format = 'jwk'; + encoding = 'json'; + } else { + priv = format; + pub = pub || format; + } + + if (!encoding) { + encoding = 'pem'; + } + + if (priv) { + priv = { type: priv, format: encoding }; + pub = { type: pub, format: encoding }; + } else { + // jwk + priv = { type: 'pkcs1', format: 'pem' }; + pub = { type: 'pkcs1', format: 'pem' }; + } + + return new Promise(function (resolve, reject) { + return require('crypto').generateKeyPair(typ, { + modulusLength: opts.modulusLength || 2048 + , publicExponent: opts.publicExponent || 0x10001 + , privateKeyEncoding: priv + , publicKeyEncoding: pub + }, function (err, pubkey, privkey) { + if (err) { reject(err); } + resolve({ + private: privkey + , public: pubkey + }); + }); + }).then(function (keypair) { + if ('jwk' !== format) { + return keypair; + } + + return { + private: RSA.importSync({ pem: keypair.private, format: priv.type }) + , public: RSA.importSync({ pem: keypair.public, format: pub.type, public: true }) + }; + }); + }); +}; + +RSA.importSync = function (opts) { + if (!opts || !opts.pem || 'string' !== typeof opts.pem) { + throw new Error("must pass { pem: pem } as a string"); + } + + var jwk = { kty: 'RSA', n: null, e: null }; + if (0 === opts.pem.indexOf('ssh-rsa ')) { + return SSH.parse(opts.pem, jwk); + } + var pem = opts.pem; + var block = PEM.parseBlock(pem); + //var hex = toHex(u8); + var asn1 = ASN1.parse(block.bytes); + + var meta = x509.guess(block.bytes, asn1); + + if ('pkcs1' === meta.format) { + jwk = x509.parsePkcs1(block.bytes, asn1, jwk); + } else { + jwk = x509.parsePkcs8(block.bytes, asn1, jwk); + } + + if (opts.public) { + jwk = RSA.nueter(jwk); + } + return jwk; +}; +RSA.parse = function parseRsa(opts) { + // wrapped in a promise for API compatibility + // with the forthcoming browser version + // (and potential future native node capability) + return Promise.resolve().then(function () { + return RSA.importSync(opts); + }); +}; +RSA.toJwk = RSA.import = RSA.parse; + +/* +RSAPrivateKey ::= SEQUENCE { + version Version, + modulus INTEGER, -- n + publicExponent INTEGER, -- e + privateExponent INTEGER, -- d + prime1 INTEGER, -- p + prime2 INTEGER, -- q + exponent1 INTEGER, -- d mod (p-1) + exponent2 INTEGER, -- d mod (q-1) + coefficient INTEGER, -- (inverse of q) mod p + otherPrimeInfos OtherPrimeInfos OPTIONAL +} +*/ + +RSA.exportSync = function (opts) { + if (!opts || !opts.jwk || 'object' !== typeof opts.jwk) { + throw new Error("must pass { jwk: jwk }"); + } + var jwk = JSON.parse(JSON.stringify(opts.jwk)); + var format = opts.format; + var pub = opts.public; + if (pub || -1 !== [ 'spki', 'pkix', 'ssh', 'rfc4716' ].indexOf(format)) { + jwk = RSA.nueter(jwk); + } + if ('RSA' !== jwk.kty) { + throw new Error("options.jwk.kty must be 'RSA' for RSA keys"); + } + if (!jwk.p) { + // TODO test for n and e + pub = true; + if (!format || 'pkcs1' === format) { + format = 'pkcs1'; + } else if (-1 !== [ 'spki', 'pkix' ].indexOf(format)) { + format = 'spki'; + } else if (-1 !== [ 'ssh', 'rfc4716' ].indexOf(format)) { + format = 'ssh'; + } else { + throw new Error("options.format must be 'spki', 'pkcs1', or 'ssh' for public RSA keys, not (" + + typeof format + ") " + format); + } + } else { + // TODO test for all necessary keys (d, p, q ...) + if (!format || 'pkcs1' === format) { + format = 'pkcs1'; + } else if ('pkcs8' !== format) { + throw new Error("options.format must be 'pkcs1' or 'pkcs8' for private RSA keys"); + } + } + + if ('pkcs1' === format) { + if (jwk.d) { + return PEM.packBlock({ type: "RSA PRIVATE KEY", bytes: x509.packPkcs1(jwk) }); + } else { + return PEM.packBlock({ type: "RSA PUBLIC KEY", bytes: x509.packPkcs1(jwk) }); + } + } else if ('pkcs8' === format) { + return PEM.packBlock({ type: "PRIVATE KEY", bytes: x509.packPkcs8(jwk) }); + } else if (-1 !== [ 'spki', 'pkix' ].indexOf(format)) { + return PEM.packBlock({ type: "PUBLIC KEY", bytes: x509.packSpki(jwk) }); + } else if (-1 !== [ 'ssh', 'rfc4716' ].indexOf(format)) { + return SSH.pack({ jwk: jwk, comment: opts.comment }); + } else { + throw new Error("Sanity Error: reached unreachable code block with format: " + format); + } +}; +RSA.pack = function (opts) { + // wrapped in a promise for API compatibility + // with the forthcoming browser version + // (and potential future native node capability) + return Promise.resolve().then(function () { + return RSA.exportSync(opts); + }); +}; +RSA.toPem = RSA.export = RSA.pack; + +// snip the _private_ parts... hAHAHAHA! +RSA.nueter = function (jwk) { + // (snip rather than new object to keep potential extra data) + // otherwise we could just do this: + // return { kty: jwk.kty, n: jwk.n, e: jwk.e }; + [ 'p', 'q', 'd', 'dp', 'dq', 'qi' ].forEach(function (key) { + if (key in jwk) { jwk[key] = undefined; } + return jwk; + }); + return jwk; +}; diff --git a/express-server/node_modules/rsa-compat/lib/rasha/lib/ssh.js b/express-server/node_modules/rsa-compat/lib/rasha/lib/ssh.js new file mode 100644 index 00000000..63041714 --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rasha/lib/ssh.js @@ -0,0 +1,80 @@ +'use strict'; + +var SSH = module.exports; +var Enc = require('./encoding.js'); + + // 7 s s h - r s a +SSH.RSA = '00000007 73 73 68 2d 72 73 61'.replace(/\s+/g, '').toLowerCase(); + +SSH.parse = function (pem, jwk) { + + var parts = pem.split(/\s+/); + var buf = Enc.base64ToBuf(parts[1]); + var els = []; + var index = 0; + var len; + var i = 0; + var offset = (buf.byteOffset || 0); + // using dataview to be browser-compatible (I do want _some_ code reuse) + var dv = new DataView(buf.buffer.slice(offset, offset + buf.byteLength)); + var el; + + if (SSH.RSA !== Enc.bufToHex(buf.slice(0, SSH.RSA.length/2))) { + throw new Error("does not lead with ssh header"); + } + + while (index < buf.byteLength) { + i += 1; + if (i > 3) { throw new Error("15+ elements, probably not a public ssh key"); } + len = dv.getUint32(index, false); + index += 4; + el = buf.slice(index, index + len); + // remove BigUInt '00' prefix + if (0x00 === el[0]) { + el = el.slice(1); + } + els.push(el); + index += len; + } + + jwk.n = Enc.bufToUrlBase64(els[2]); + jwk.e = Enc.bufToUrlBase64(els[1]); + + return jwk; +}; + +SSH.pack = function (opts) { + var jwk = opts.jwk; + var header = 'ssh-rsa'; + var comment = opts.comment || 'rsa@localhost'; + var e = SSH._padHexInt(Enc.base64ToHex(jwk.e)); + var n = SSH._padHexInt(Enc.base64ToHex(jwk.n)); + var hex = [ + SSH._numToUint32Hex(header.length) + , Enc.strToHex(header) + , SSH._numToUint32Hex(e.length/2) + , e + , SSH._numToUint32Hex(n.length/2) + , n + ].join(''); + return [ header, Enc.hexToBase64(hex), comment ].join(' '); +}; + +SSH._numToUint32Hex = function (num) { + var hex = num.toString(16); + while (hex.length < 8) { + hex = '0' + hex; + } + return hex; +}; + +SSH._padHexInt = function (hex) { + // BigInt is negative if the high order bit 0x80 is set, + // so ASN1, SSH, and many other formats pad with '0x00' + // to signifiy a positive number. + var i = parseInt(hex.slice(0, 2), 16); + if (0x80 & i) { + return '00' + hex; + } + return hex; +}; diff --git a/express-server/node_modules/rsa-compat/lib/rasha/lib/telemetry.js b/express-server/node_modules/rsa-compat/lib/rasha/lib/telemetry.js new file mode 100644 index 00000000..9623b775 --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rasha/lib/telemetry.js @@ -0,0 +1,111 @@ +'use strict'; + +// We believe in a proactive approach to sustainable open source. +// As part of that we make it easy for you to opt-in to following our progress +// and we also stay up-to-date on telemetry such as operating system and node +// version so that we can focus our efforts where they'll have the greatest impact. +// +// Want to learn more about our Terms, Privacy Policy, and Mission? +// Check out https://therootcompany.com/legal/ + +var os = require('os'); +var crypto = require('crypto'); +var https = require('https'); +var pkg = require('../package.json'); + +// to help focus our efforts in the right places +var data = { + package: pkg.name +, version: pkg.version +, node: process.version +, arch: process.arch || os.arch() +, platform: process.platform || os.platform() +, release: os.release() +}; + +function addCommunityMember(opts) { + setTimeout(function () { + var req = https.request({ + hostname: 'api.therootcompany.com' + , port: 443 + , path: '/api/therootcompany.com/public/community' + , method: 'POST' + , headers: { 'Content-Type': 'application/json' } + }, function (resp) { + // let the data flow, so we can ignore it + resp.on('data', function () {}); + //resp.on('data', function (chunk) { console.log(chunk.toString()); }); + resp.on('error', function () { /*ignore*/ }); + //resp.on('error', function (err) { console.error(err); }); + }); + var obj = JSON.parse(JSON.stringify(data)); + obj.action = 'updates'; + try { + obj.ppid = ppid(obj.action); + } catch(e) { + // ignore + //console.error(e); + } + obj.name = opts.name || undefined; + obj.address = opts.email; + obj.community = 'node.js@therootcompany.com'; + + req.write(JSON.stringify(obj, 2, null)); + req.end(); + req.on('error', function () { /*ignore*/ }); + //req.on('error', function (err) { console.error(err); }); + }, 50); +} + +function ping(action) { + setTimeout(function () { + var req = https.request({ + hostname: 'api.therootcompany.com' + , port: 443 + , path: '/api/therootcompany.com/public/ping' + , method: 'POST' + , headers: { 'Content-Type': 'application/json' } + }, function (resp) { + // let the data flow, so we can ignore it + resp.on('data', function () { }); + //resp.on('data', function (chunk) { console.log(chunk.toString()); }); + resp.on('error', function () { /*ignore*/ }); + //resp.on('error', function (err) { console.error(err); }); + }); + var obj = JSON.parse(JSON.stringify(data)); + obj.action = action; + try { + obj.ppid = ppid(obj.action); + } catch(e) { + // ignore + //console.error(e); + } + + req.write(JSON.stringify(obj, 2, null)); + req.end(); + req.on('error', function (/*e*/) { /*console.error('req.error', e);*/ }); + }, 50); +} + +// to help identify unique installs without getting +// the personally identifiable info that we don't want +function ppid(action) { + var parts = [ action, data.package, data.version, data.node, data.arch, data.platform, data.release ]; + var ifaces = os.networkInterfaces(); + Object.keys(ifaces).forEach(function (ifname) { + if (/^en/.test(ifname) || /^eth/.test(ifname) || /^wl/.test(ifname)) { + if (ifaces[ifname] && ifaces[ifname].length) { + parts.push(ifaces[ifname][0].mac); + } + } + }); + return crypto.createHash('sha1').update(parts.join(',')).digest('base64'); +} + +module.exports.ping = ping; +module.exports.joinCommunity = addCommunityMember; + +if (require.main === module) { + ping('install'); + //addCommunityMember({ name: "AJ ONeal", email: 'coolaj86@gmail.com' }); +} diff --git a/express-server/node_modules/rsa-compat/lib/rasha/lib/x509.js b/express-server/node_modules/rsa-compat/lib/rasha/lib/x509.js new file mode 100644 index 00000000..fb193e16 --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rasha/lib/x509.js @@ -0,0 +1,153 @@ +'use strict'; + +var x509 = module.exports; +var ASN1 = require('./asn1.js'); +var Enc = require('./encoding.js'); + +x509.guess = function (der, asn1) { + // accepting der for compatability with other usages + + var meta = { kty: 'RSA', format: 'pkcs1', public: true }; + //meta.asn1 = ASN1.parse(u8); + + if (asn1.children.every(function(el) { + return 0x02 === el.type; + })) { + if (2 === asn1.children.length) { + // rsa pkcs1 public + return meta; + } else if (asn1.children.length >= 9) { + // the standard allows for "otherPrimeInfos", hence at least 9 + meta.public = false; + // rsa pkcs1 private + return meta; + } else { + throw new Error("not an RSA PKCS#1 public or private key (wrong number of ints)"); + } + } else { + meta.format = 'pkcs8'; + } + + return meta; +}; + +x509.parsePkcs1 = function parseRsaPkcs1(buf, asn1, jwk) { + if (!asn1.children.every(function(el) { + return 0x02 === el.type; + })) { + throw new Error("not an RSA PKCS#1 public or private key (not all ints)"); + } + + if (2 === asn1.children.length) { + + jwk.n = Enc.bufToUrlBase64(asn1.children[0].value); + jwk.e = Enc.bufToUrlBase64(asn1.children[1].value); + return jwk; + + } else if (asn1.children.length >= 9) { + // the standard allows for "otherPrimeInfos", hence at least 9 + + jwk.n = Enc.bufToUrlBase64(asn1.children[1].value); + jwk.e = Enc.bufToUrlBase64(asn1.children[2].value); + jwk.d = Enc.bufToUrlBase64(asn1.children[3].value); + jwk.p = Enc.bufToUrlBase64(asn1.children[4].value); + jwk.q = Enc.bufToUrlBase64(asn1.children[5].value); + jwk.dp = Enc.bufToUrlBase64(asn1.children[6].value); + jwk.dq = Enc.bufToUrlBase64(asn1.children[7].value); + jwk.qi = Enc.bufToUrlBase64(asn1.children[8].value); + return jwk; + + } else { + throw new Error("not an RSA PKCS#1 public or private key (wrong number of ints)"); + } +}; + +x509.parsePkcs8 = function parseRsaPkcs8(buf, asn1, jwk) { + if (2 === asn1.children.length + && 0x03 === asn1.children[1].type + && 0x30 === asn1.children[1].value[0]) { + + asn1 = ASN1.parse(asn1.children[1].value); + jwk.n = Enc.bufToUrlBase64(asn1.children[0].value); + jwk.e = Enc.bufToUrlBase64(asn1.children[1].value); + + } else if (3 === asn1.children.length + && 0x04 === asn1.children[2].type + && 0x30 === asn1.children[2].children[0].type + && 0x02 === asn1.children[2].children[0].children[0].type) { + + asn1 = asn1.children[2].children[0]; + jwk.n = Enc.bufToUrlBase64(asn1.children[1].value); + jwk.e = Enc.bufToUrlBase64(asn1.children[2].value); + jwk.d = Enc.bufToUrlBase64(asn1.children[3].value); + jwk.p = Enc.bufToUrlBase64(asn1.children[4].value); + jwk.q = Enc.bufToUrlBase64(asn1.children[5].value); + jwk.dp = Enc.bufToUrlBase64(asn1.children[6].value); + jwk.dq = Enc.bufToUrlBase64(asn1.children[7].value); + jwk.qi = Enc.bufToUrlBase64(asn1.children[8].value); + + } else { + throw new Error("not an RSA PKCS#8 public or private key (wrong format)"); + } + return jwk; +}; + +x509.packPkcs1 = function (jwk) { + var n = ASN1.UInt(Enc.base64ToHex(jwk.n)); + var e = ASN1.UInt(Enc.base64ToHex(jwk.e)); + + if (!jwk.d) { + return Enc.hexToBuf(ASN1('30', n, e)); + } + + return Enc.hexToBuf(ASN1('30' + , ASN1.UInt('00') + , n + , e + , ASN1.UInt(Enc.base64ToHex(jwk.d)) + , ASN1.UInt(Enc.base64ToHex(jwk.p)) + , ASN1.UInt(Enc.base64ToHex(jwk.q)) + , ASN1.UInt(Enc.base64ToHex(jwk.dp)) + , ASN1.UInt(Enc.base64ToHex(jwk.dq)) + , ASN1.UInt(Enc.base64ToHex(jwk.qi)) + )); +}; + +x509.packPkcs8 = function (jwk) { + if (!jwk.d) { + // Public RSA + return Enc.hexToBuf(ASN1('30' + , ASN1('30' + , ASN1('06', '2a864886f70d010101') + , ASN1('05') + ) + , ASN1.BitStr(ASN1('30' + , ASN1.UInt(Enc.base64ToHex(jwk.n)) + , ASN1.UInt(Enc.base64ToHex(jwk.e)) + )) + )); + } + + // Private RSA + return Enc.hexToBuf(ASN1('30' + , ASN1.UInt('00') + , ASN1('30' + , ASN1('06', '2a864886f70d010101') + , ASN1('05') + ) + , ASN1('04' + , ASN1('30' + , ASN1.UInt('00') + , ASN1.UInt(Enc.base64ToHex(jwk.n)) + , ASN1.UInt(Enc.base64ToHex(jwk.e)) + , ASN1.UInt(Enc.base64ToHex(jwk.d)) + , ASN1.UInt(Enc.base64ToHex(jwk.p)) + , ASN1.UInt(Enc.base64ToHex(jwk.q)) + , ASN1.UInt(Enc.base64ToHex(jwk.dp)) + , ASN1.UInt(Enc.base64ToHex(jwk.dq)) + , ASN1.UInt(Enc.base64ToHex(jwk.qi)) + ) + ) + )); +}; +x509.packSpki = x509.packPkcs8; diff --git a/express-server/node_modules/rsa-compat/lib/rsa-csr/README.md b/express-server/node_modules/rsa-compat/lib/rsa-csr/README.md new file mode 100644 index 00000000..108d55ae --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rsa-csr/README.md @@ -0,0 +1,214 @@ +[RSA-CSR.js](https://git.coolaj86.com/coolaj86/rsa-csr.js) +========== + +Sponsored by [Root](https://therootcompany.com), +built for [ACME.js](https://git.coolaj86.com/coolaj86/acme.js) +and [Greenlock.js](https://git.coolaj86.com/coolaj86/greenlock-express.js) + +A focused, **zero-dependency** library that can do exactly one thing really, really well: + * Generate a Certificate Signing Requests (CSR), and sign it! + +| < 300 lines of code | 1.7k gzipped | 4.7k minified | 8.5k with comments | + +Need JWK-to-PEM? Try [Rasha.js](https://git.coolaj86.com/coolaj86/rasha.js) + +Need to generate an EC CSR? Try [ECSDA-CSR.js](https://git.coolaj86.com/coolaj86/ecdsa-csr.js) + +Features +======== + +* [x] Universal CSR support (RSA signing) that Just Works™ + * Common Name (CN) Subject + * Subject Alternative Names (SANs / altnames) + * 2048, 3072, and 4096 bit JWK RSA + * RSASSA PKCS1 v1.5 +* [x] Zero Dependencies + * (no ASN1.js, PKI.js, forge, jrsasign - not even elliptic.js!) +* [x] Quality + * Focused + * Lightweight + * Well-Commented, Well-Documented + * Secure +* [x] Vanilla Node.js + * no school like the old school + * easy to read and understand + +Usage +----- + +Given an array of domains it uses the first for the Common Name (CN), +also known as Subject, and all of them as the Subject Alternative Names (SANs or altnames). + +```js +'use strict'; + +var rsacsr = require('rsa-csr'); +var key = { + "kty": "RSA", + "n": "m2tt...-CNw", + "e": "AQAB", + "d": "Cpfo...HMQQ", + "p": "ynG-...sTCE", + "q": "xIkA...1Q1c", + "dp": "tzDG...B1QE", + "dq": "kh5d...aL48", + "qi": "AlHW...HhFU" +}; +var domains = [ 'example.com', 'www.example.com' ]; + +return rsacsr({ key: key, domains: domains }).then(function (csr) { + console.log('CSR PEM:'); + console.log(csr); +}); +``` + +The output will look something like this (but much longer): + +``` +-----BEGIN CERTIFICATE REQUEST----- +MIIClTCCAX0CAQAwFjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCba21UHE+VbDTpmYYFZUOV+OQ8AngOCdjROsPC +0KiEfMvEaEM3NQl58u6QL7G7QsEr.....3pIpUUkx5WbwJY6xDrCyFKG8ktpnee6 +WjpTOBnpgHUI1/5ydnf0v29L9N+ALIJGKQxhub3iqB6EhCl93iiQtf4e7M/lzX7l +c1xqsSwVZ3RQVY9bRP9NdGuW4hVvscy5ypqRtXPXQpxMnYwfi9qW5Uo= +-----END CERTIFICATE REQUEST----- +``` + +#### PEM-to-JWK + +If you need to convert a PEM to JWK first, do so: + +```js +var Rasha = require('rasha'); + +Rasha.import({ pem: "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAI..." }).then(function (jwk) { + console.log(jwk); +}) +``` + +#### CLI + +You're probably better off using OpenSSL for most commandline tasks, +but the `rsa-csr` and `rasha` CLIs are useful for testing and debugging. + +```bash +npm install -g rsa-csr +npm install -g rasha + +rasha ./privkey.pem > ./privkey.jwk.json +rsa-csr ./privkey.jwk.json example.com,www.example.com > csr.pem +``` + +### Options + +* `key` should be a JWK + * Need PEM support? Use [Rasha.js](https://git.coolaj86.com/coolaj86/rasha.js). + * (supports PEM, DER, PKCS#1 and PKCS#8) +* `domains` must be a list of strings representing domain names + * correctly handles utf-8 + * you may also use punycoded, if needed +* `subject` will be `domains[0]` by default + * you shouldn't use this unless you need to + * you may need to if you need utf-8 for domains, but punycode for the subject + +### Testing + +You can double check that the CSR you get out is actually valid: + +```bash +# Generate a key, if needed +openssl genrsa -out ./privkey-rsa.pkcs1.pem $keysize + +# Convert to JWK +rasha ./privkey-rsa.pkcs1.pem > ./privkey-rsa.jwk.json + +# Create a CSR with your domains +npx rsa-csr ./privkey-rsa.jwk.json example.com,www.example.com > csr.pem + +# Verify +openssl req -text -noout -verify -in csr.pem +``` + +New to Crypto? +-------------- + +Just a heads up in case you have no idea what you're doing: + +First of all, [don't panic](https://coolaj86.com/articles/dont-panic.html). + +Next: + +* RSA stands for... well, that doesn't matter, actually. +* DSA stands for _Digital Signing Algorithm_. +* RSA a separate standard from EC/ECDSA, but both are *asymmetric* +* Private keys are actually keypairs (they contain the public key) + +In many cases the terms get used (and misused) interchangably, +which can be confusing. You'll survive, I promise. + +* PEM is just a Base64-encoded DER (think JSON as hex or base64) +* DER is an binary _object notation_ for ASN.1 (think actual stringified JSON or XML) +* ASN.1 is _object notation_ standard (think JSON, the standard) +* X.509 is a suite of schemas (think XLST or json-schema.org) +* PKCS#8, PKIK, SPKI are all X.509 schemas (think defining `firstName` vs `first_name` vs `firstname`) + +Now forget about all that and just know this: + +**This library solves your problem if** you need RSA _something-or-other_ and CSR _something-or-other_ +in order to deal with SSL certificates in an internal organization. + +If that's not what you're doing, you may want HTTPS and SSL through +[Greenlock.js](https://git.coolaj86.com/coolaj86/greenlock-express.js), +or you may be looking for something else entirely. + +Goals vs Non-Goals +----- + +This was built for use by [ACME.js](https://git.coolaj86.com/coolaj86/acme.js) +and [Greenlock.js](https://git.coolaj86.com/coolaj86/greenlock-express.js). + +Rather than trying to make a generic implementation that works with everything under the sun, +this library is intentionally focused on around the use case of generating certificates for +ACME services (such as Let's Encrypt). + +That said, [please tell me](https://git.coolaj86.com/coolaj86/rsa-csr.js/issues) if it doesn't +do what you need, it may make sense to add it (or otherwise, perhaps to help you create a fork). + +The primary goal of this project is for this code to do exactly (and all of) +what it needs to do - No more, no less. + +* Support RSA JWKs + * 2048-bit + * 3072-bit + * 4096-bit +* Support PEM and DER via Rasha.js + * PKCS#1 (traditional) + * PKCS#8 + * RSASSA-PKCS1-v1_5 +* Vanilla node.js (ECMAScript 5.1) + * No babel + * No dependencies + +However, there are a few areas where I'd be willing to stretch: + +* Type definition files for altscript languages + +It is not a goal of this project to support any RSA profiles +except those that are universally supported by browsers and +are sufficiently secure (overkill is overkill). + +> A little copying is better than a little dependency. - [Go Proverbs](https://go-proverbs.github.io) by Rob Pike + +This code is considered small and focused enough that, +rather than making it a dependency in other small projects, +I personally just copy over the code. + +Hence, all of these projects are MPL-2.0 licensed. + +Legal +----- + +[RSA-CSR.js](https://git.coolaj86.com/coolaj86/rsa-csr.js) | +MPL-2.0 | +[Terms of Use](https://therootcompany.com/legal/#terms) | +[Privacy Policy](https://therootcompany.com/legal/#privacy) diff --git a/express-server/node_modules/rsa-compat/lib/rsa-csr/bin/rsa-csr.js b/express-server/node_modules/rsa-compat/lib/rsa-csr/bin/rsa-csr.js new file mode 100644 index 00000000..a9233305 --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rsa-csr/bin/rsa-csr.js @@ -0,0 +1,23 @@ +#!/usr/bin/env node +'use strict'; + +var fs = require('fs'); +var rsacsr = require('../index.js'); + +var keyname = process.argv[2]; +var domains = process.argv[3].split(/,/); + +var key = fs.readFileSync(keyname, 'ascii'); + +try { + key = JSON.parse(key); +} catch(e) { + // ignore +} + +rsacsr({ key: key, domains: domains }).then(function (csr) { + // Using error so that we can redirect stdout to file + //console.error("CN=" + domains[0]); + //console.error("subjectAltName=" + domains.join(',')); + console.log(csr); +}); diff --git a/express-server/node_modules/rsa-compat/lib/rsa-csr/fixtures/example.com-www.csr.pem b/express-server/node_modules/rsa-compat/lib/rsa-csr/fixtures/example.com-www.csr.pem new file mode 100644 index 00000000..d876ff8e --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rsa-csr/fixtures/example.com-www.csr.pem @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIClTCCAX0CAQAwFjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCba21UHE+VbDTpmYYFZUOV+OQ8AngOCdjROsPC +0KiEfMvEaEM3NQl58u6QL7G7QsErKViiNPm9OTFo6HF5JijfWzK7haHFuRMEsgI4 +VwIYyhvqlJDfw/wt0AiVvSmoMfEQn1p1aiaO4V/RJSE3Vw/uz2bxiT22uSkSqOyS +hyfYE6dMHnuoBkzr4jvSifT+INmbv6Nyo4+AAMCZtYeHLrsFeSTjLL9jMPjI4ZkV +dlw2n3Xn9NbltF3/8Ao8dQfElqw+LIQWqU0oFHYNIP4ttfl5ObMKHaKSvBMyNruZ +R0El/ZsrcHLkAHRCLj07KRQJ81l5CUTPtQ02P1Eamz/nT4I3AgMBAAGgOjA4Bgkq +hkiG9w0BCQ4xKzApMCcGA1UdEQQgMB6CC2V4YW1wbGUuY29tgg93d3cuZXhhbXBs +ZS5jb20wDQYJKoZIhvcNAQELBQADggEBAGOFydCZPtRqnEidrB3vkpPp1GmQVqrl +XhqVM3X7UppsD3QDtJfgoSuBuVy3X/mPvy/Ly8WqEwJ7Ur+h76e7rgeFLvN5fQIr +frlpfCXrKaxxl6vxqKJ8s3Mn2LT8VmSVNig34NCtn99/SHNAlr3aU9L3b1+R25VI +FwFbOz/i92gOchT7Xat3fOiQ02k9GrHT33pIpUUkx5WbwJY6xDrCyFKG8ktpnee6 +WjpTOBnpgHUI1/5ydnf0v29L9N+ALIJGKQxhub3iqB6EhCl93iiQtf4e7M/lzX7l +c1xqsSwVZ3RQVY9bRP9NdGuW4hVvscy5ypqRtXPXQpxMnYwfi9qW5Uo= +-----END CERTIFICATE REQUEST----- diff --git a/express-server/node_modules/rsa-compat/lib/rsa-csr/fixtures/privkey-rsa-2048.jwk.json b/express-server/node_modules/rsa-compat/lib/rsa-csr/fixtures/privkey-rsa-2048.jwk.json new file mode 100644 index 00000000..f344c22f --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rsa-csr/fixtures/privkey-rsa-2048.jwk.json @@ -0,0 +1,11 @@ +{ + "kty": "RSA", + "n": "m2ttVBxPlWw06ZmGBWVDlfjkPAJ4DgnY0TrDwtCohHzLxGhDNzUJefLukC-xu0LBKylYojT5vTkxaOhxeSYo31syu4WhxbkTBLICOFcCGMob6pSQ38P8LdAIlb0pqDHxEJ9adWomjuFf0SUhN1cP7s9m8Yk9trkpEqjskocn2BOnTB57qAZM6-I70on0_iDZm7-jcqOPgADAmbWHhy67BXkk4yy_YzD4yOGZFXZcNp915_TW5bRd__AKPHUHxJasPiyEFqlNKBR2DSD-LbX5eTmzCh2ikrwTMja7mUdBJf2bK3By5AB0Qi49OykUCfNZeQlEz7UNNj9RGps_50-CNw", + "e": "AQAB", + "d": "Cpfo7Mm9Nu8YMC_xrZ54W9mKHPkCG9rZ93Ds9PNp-RXUgb-ljTbFPZWsYxGNKLllFz8LNosr1pT2ZDMrwNk0Af1iWNvD6gkyXaiQdCyiDPSBsJyNv2LJZon-e85X74nv53UlIkmo9SYxdLz2JaJ-iIWEe8Qh-7llLktrTJV_xr98_tbhgSppz_IeOymq3SEZaQHM8pTU7w7XvCj2pb9r8fN0M0XcgWZIaf3LGEfkhF_WtX67XJ0C6-LbkT51jtlLRNGX6haGdscXS0OWWjKOJzKGuV-NbthEn5rmRtVnjRZ3yaxQ0ud8vC-NONn7yvGUlOur1IdDzJ_YfHPt9sHMQQ", + "p": "ynG-t9HwKCN3MWRYFdnFzi9-02Qcy3p8B5pu3ary2E70hYn2pHlUG2a9BNE8c5xHQ3Hx43WoWf6s0zOunPV1G28LkU_UYEbAtPv_PxSmzpQp9n9XnYvBLBF8Y3z7gxgLn1vVFNARrQdRtj87qY3aw7E9S4DsGcAarIuOT2TsTCE", + "q": "xIkAjgUzB1zaUzJtW2Zgvp9cYYr1DmpH30ePZl3c_8397_DZDDo46fnFYjs6uPa03HpmKUnbjwr14QHlfXlntJBEuXxcqLjkdKdJ4ob7xueLTK4suo9V8LSrkLChVxlZQwnFD2E5ll0sVeeDeMJHQw38ahSrBFEVnxjpnPh1Q1c", + "dp": "tzDGjECFOU0ehqtuqhcuT63a7h8hj19-7MJqoFwY9HQ-ALkfXyYLXeBSGxHbyiIYuodZg6LsfMNgUJ3r3Eyhc_nAVfYPEC_2IdAG4WYmq7iXYF9LQV09qEsKbFykm7QekE3hO7wswo5k-q2tp3ieBYdVGAXJoGOdv5VpaZ7B1QE", + "dq": "kh5dyDk7YCz7sUFbpsmuAeuPjoH2ghooh2u3xN7iUVmAg-ToKjwbVnG5-7eXiC779rQVwnrD_0yh1AFJ8wjRPqDIR7ObXGHikIxT1VSQWqiJm6AfZzDsL0LUD4YS3iPdhob7-NxLKWzqao_u4lhnDQaX9PKa12HFlny6K1daL48", + "qi": "AlHWbx1gp6Z9pbw_1hlS7HuXAgWoX7IjbTUelldf4gkriDWLOrj3QCZcO4ZvZvEwJhVlsny9LO8IkbwGJEL6cXraK08ByVS2mwQyflgTgGNnpzixyEUL_mrQLx6y145FHcxfeqNInMhep-0Mxn1D5nlhmIOgRApS0t9VoXtHhFU" +} diff --git a/express-server/node_modules/rsa-compat/lib/rsa-csr/fixtures/privkey-rsa-2048.pkcs1.pem b/express-server/node_modules/rsa-compat/lib/rsa-csr/fixtures/privkey-rsa-2048.pkcs1.pem new file mode 100644 index 00000000..246bd35c --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rsa-csr/fixtures/privkey-rsa-2048.pkcs1.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAm2ttVBxPlWw06ZmGBWVDlfjkPAJ4DgnY0TrDwtCohHzLxGhD +NzUJefLukC+xu0LBKylYojT5vTkxaOhxeSYo31syu4WhxbkTBLICOFcCGMob6pSQ +38P8LdAIlb0pqDHxEJ9adWomjuFf0SUhN1cP7s9m8Yk9trkpEqjskocn2BOnTB57 +qAZM6+I70on0/iDZm7+jcqOPgADAmbWHhy67BXkk4yy/YzD4yOGZFXZcNp915/TW +5bRd//AKPHUHxJasPiyEFqlNKBR2DSD+LbX5eTmzCh2ikrwTMja7mUdBJf2bK3By +5AB0Qi49OykUCfNZeQlEz7UNNj9RGps/50+CNwIDAQABAoIBAAqX6OzJvTbvGDAv +8a2eeFvZihz5Ahva2fdw7PTzafkV1IG/pY02xT2VrGMRjSi5ZRc/CzaLK9aU9mQz +K8DZNAH9Yljbw+oJMl2okHQsogz0gbCcjb9iyWaJ/nvOV++J7+d1JSJJqPUmMXS8 +9iWifoiFhHvEIfu5ZS5La0yVf8a/fP7W4YEqac/yHjspqt0hGWkBzPKU1O8O17wo +9qW/a/HzdDNF3IFmSGn9yxhH5IRf1rV+u1ydAuvi25E+dY7ZS0TRl+oWhnbHF0tD +lloyjicyhrlfjW7YRJ+a5kbVZ40Wd8msUNLnfLwvjTjZ+8rxlJTrq9SHQ8yf2Hxz +7fbBzEECgYEAynG+t9HwKCN3MWRYFdnFzi9+02Qcy3p8B5pu3ary2E70hYn2pHlU +G2a9BNE8c5xHQ3Hx43WoWf6s0zOunPV1G28LkU/UYEbAtPv/PxSmzpQp9n9XnYvB +LBF8Y3z7gxgLn1vVFNARrQdRtj87qY3aw7E9S4DsGcAarIuOT2TsTCECgYEAxIkA +jgUzB1zaUzJtW2Zgvp9cYYr1DmpH30ePZl3c/8397/DZDDo46fnFYjs6uPa03Hpm +KUnbjwr14QHlfXlntJBEuXxcqLjkdKdJ4ob7xueLTK4suo9V8LSrkLChVxlZQwnF +D2E5ll0sVeeDeMJHQw38ahSrBFEVnxjpnPh1Q1cCgYEAtzDGjECFOU0ehqtuqhcu +T63a7h8hj19+7MJqoFwY9HQ+ALkfXyYLXeBSGxHbyiIYuodZg6LsfMNgUJ3r3Eyh +c/nAVfYPEC/2IdAG4WYmq7iXYF9LQV09qEsKbFykm7QekE3hO7wswo5k+q2tp3ie +BYdVGAXJoGOdv5VpaZ7B1QECgYEAkh5dyDk7YCz7sUFbpsmuAeuPjoH2ghooh2u3 +xN7iUVmAg+ToKjwbVnG5+7eXiC779rQVwnrD/0yh1AFJ8wjRPqDIR7ObXGHikIxT +1VSQWqiJm6AfZzDsL0LUD4YS3iPdhob7+NxLKWzqao/u4lhnDQaX9PKa12HFlny6 +K1daL48CgYACUdZvHWCnpn2lvD/WGVLse5cCBahfsiNtNR6WV1/iCSuINYs6uPdA +Jlw7hm9m8TAmFWWyfL0s7wiRvAYkQvpxetorTwHJVLabBDJ+WBOAY2enOLHIRQv+ +atAvHrLXjkUdzF96o0icyF6n7QzGfUPmeWGYg6BEClLS31Whe0eEVQ== +-----END RSA PRIVATE KEY----- diff --git a/express-server/node_modules/rsa-compat/lib/rsa-csr/fixtures/whatever.net-www-api.csr.pem b/express-server/node_modules/rsa-compat/lib/rsa-csr/fixtures/whatever.net-www-api.csr.pem new file mode 100644 index 00000000..9275f2dd --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rsa-csr/fixtures/whatever.net-www-api.csr.pem @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICqjCCAZICAQAwFzEVMBMGA1UEAwwMd2hhdGV2ZXIubmV0MIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm2ttVBxPlWw06ZmGBWVDlfjkPAJ4DgnY0TrD +wtCohHzLxGhDNzUJefLukC+xu0LBKylYojT5vTkxaOhxeSYo31syu4WhxbkTBLIC +OFcCGMob6pSQ38P8LdAIlb0pqDHxEJ9adWomjuFf0SUhN1cP7s9m8Yk9trkpEqjs +kocn2BOnTB57qAZM6+I70on0/iDZm7+jcqOPgADAmbWHhy67BXkk4yy/YzD4yOGZ +FXZcNp915/TW5bRd//AKPHUHxJasPiyEFqlNKBR2DSD+LbX5eTmzCh2ikrwTMja7 +mUdBJf2bK3By5AB0Qi49OykUCfNZeQlEz7UNNj9RGps/50+CNwIDAQABoE4wTAYJ +KoZIhvcNAQkOMT8wPTA7BgNVHREENDAyggx3aGF0ZXZlci5uZXSCEHd3dy53aGF0 +ZXZlci5uZXSCEGFwaS53aGF0ZXZlci5uZXQwDQYJKoZIhvcNAQELBQADggEBAB21 +KZYjarfd8nUAbwhH8dWZOo4rFcdYFo3xcXPQ11b1Wa79dtG67cgD/dplKFis5qD3 +6h4m818w9ESBA3Q1ZUy6HgDPMhCjg2fmCnSsZ5epo47wzvelYonfOX5DAwxgfYsa +335olrXJ0qsTiNmaS7RxDT53vfMOp41NyEAkFmpIAkaHgW/+xFPUSCBXIUWbaCG+ +pK3FVNmK3VCVCAP6UvVKYQUWSC6FRG/Q8MHoecdo+bbMlr2s2GPxq9TKInwe8JqT +E9pD7QMsN7uWpMaXNKCje4+Q88Br4URNcGAiYoy4/6hcF2Ki1saTYVIk/DG1P4hX +G5f0ezDLtsC22xe6jHI= +-----END CERTIFICATE REQUEST----- diff --git a/express-server/node_modules/rsa-compat/lib/rsa-csr/index.js b/express-server/node_modules/rsa-compat/lib/rsa-csr/index.js new file mode 100644 index 00000000..a4b74e68 --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rsa-csr/index.js @@ -0,0 +1,2 @@ +'use strict'; +module.exports = require('./lib/csr.js'); diff --git a/express-server/node_modules/rsa-compat/lib/rsa-csr/lib/asn1.js b/express-server/node_modules/rsa-compat/lib/rsa-csr/lib/asn1.js new file mode 100644 index 00000000..c92c1c31 --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rsa-csr/lib/asn1.js @@ -0,0 +1,72 @@ +'use strict'; + +// +// A dumbed-down, minimal ASN.1 parser / packer combo +// +// Note: generally I like to write congruent code +// (i.e. output can be used as input and vice-versa) +// However, this seemed to be more readable and easier +// to use written as-is, asymmetrically. +// (I also generally prefer to export objects rather +// functions but, yet again, asthetics one in this case) + +var Enc = require('./encoding.js'); + +// +// Packer +// + +// Almost every ASN.1 type that's important for CSR +// can be represented generically with only a few rules. +var ASN1 = module.exports = function ASN1(/*type, hexstrings...*/) { + var args = Array.prototype.slice.call(arguments); + var typ = args.shift(); + var str = args.join('').replace(/\s+/g, '').toLowerCase(); + var len = (str.length/2); + var lenlen = 0; + var hex = typ; + + // We can't have an odd number of hex chars + if (len !== Math.round(len)) { + console.error(arguments); + throw new Error("invalid hex"); + } + + // The first byte of any ASN.1 sequence is the type (Sequence, Integer, etc) + // The second byte is either the size of the value, or the size of its size + + // 1. If the second byte is < 0x80 (128) it is considered the size + // 2. If it is > 0x80 then it describes the number of bytes of the size + // ex: 0x82 means the next 2 bytes describe the size of the value + // 3. The special case of exactly 0x80 is "indefinite" length (to end-of-file) + + if (len > 127) { + lenlen += 1; + while (len > 255) { + lenlen += 1; + len = len >> 8; + } + } + + if (lenlen) { hex += Enc.numToHex(0x80 + lenlen); } + return hex + Enc.numToHex(str.length/2) + str; +}; + +// The Integer type has some special rules +ASN1.UInt = function UINT() { + var str = Array.prototype.slice.call(arguments).join(''); + var first = parseInt(str.slice(0, 2), 16); + + // If the first byte is 0x80 or greater, the number is considered negative + // Therefore we add a '00' prefix if the 0x80 bit is set + if (0x80 & first) { str = '00' + str; } + + return ASN1('02', str); +}; + +// The Bit String type also has a special rule +ASN1.BitStr = function BITSTR() { + var str = Array.prototype.slice.call(arguments).join(''); + // '00' is a mask of how many bits of the next byte to ignore + return ASN1('03', '00' + str); +}; diff --git a/express-server/node_modules/rsa-compat/lib/rsa-csr/lib/csr.js b/express-server/node_modules/rsa-compat/lib/rsa-csr/lib/csr.js new file mode 100644 index 00000000..219ab273 --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rsa-csr/lib/csr.js @@ -0,0 +1,152 @@ +'use strict'; + +var crypto = require('crypto'); +var ASN1 = require('./asn1.js'); +var Enc = require('./encoding.js'); +var PEM = require('./pem.js'); +var X509 = require('./x509.js'); +var RSA = {}; + +/*global Promise*/ +var CSR = module.exports = function rsacsr(opts) { + // We're using a Promise here to be compatible with the browser version + // which will probably use the webcrypto API for some of the conversions + opts = CSR._prepare(opts); + + return CSR.create(opts).then(function (bytes) { + return CSR._encode(opts, bytes); + }); +}; + +CSR._prepare = function (opts) { + var Rasha; + opts = JSON.parse(JSON.stringify(opts)); + var pem, jwk; + + // We do a bit of extra error checking for user convenience + if (!opts) { throw new Error("You must pass options with key and domains to rsacsr"); } + if (!Array.isArray(opts.domains) || 0 === opts.domains.length) { + new Error("You must pass options.domains as a non-empty array"); + } + + // I need to check that 例.中国 is a valid domain name + if (!opts.domains.every(function (d) { + // allow punycode? xn-- + if ('string' === typeof d /*&& /\./.test(d) && !/--/.test(d)*/) { + return true; + } + })) { + throw new Error("You must pass options.domains as strings"); + } + + if (opts.pem) { + pem = opts.pem; + } else if (opts.jwk) { + jwk = opts.jwk; + } else { + if (!opts.key) { + throw new Error("You must pass options.key as a JSON web key"); + } else if (opts.key.kty) { + jwk = opts.key; + } else { + pem = opts.key; + } + } + + if (pem) { + try { + Rasha = require('rasha'); + } catch(e) { + throw new Error("Rasha.js is an optional dependency for PEM-to-JWK.\n" + + "Install it if you'd like to use it:\n" + + "\tnpm install --save rasha\n" + + "Otherwise supply a jwk as the private key." + ); + } + jwk = Rasha.importSync({ pem: pem }); + } + + opts.jwk = jwk; + return opts; +}; +CSR.sync = function (opts) { + opts = CSR._prepare(opts); + var bytes = CSR.createSync(opts); + return CSR._encode(opts, bytes); +}; +CSR._encode = function (opts, bytes) { + if ('der' === (opts.encoding||'').toLowerCase()) { + return bytes; + } + return PEM.packBlock({ + type: "CERTIFICATE REQUEST" + , bytes: bytes /* { jwk: jwk, domains: opts.domains } */ + }); +}; + +CSR.createSync = function createCsr(opts) { + var hex = CSR.request(opts.jwk, opts.domains); + var csr = CSR.signSync(opts.jwk, hex); + return Enc.hexToBuf(csr); +}; +CSR.create = function createCsr(opts) { + var hex = CSR.request(opts.jwk, opts.domains); + return CSR.sign(opts.jwk, hex).then(function (csr) { + return Enc.hexToBuf(csr); + }); +}; + +CSR.request = function createCsrBodyEc(jwk, domains) { + var asn1pub = X509.packCsrPublicKey(jwk); + return X509.packCsr(asn1pub, domains); +}; + +CSR.signSync = function csrEcSig(jwk, request) { + var keypem = PEM.packBlock({ type: "RSA PRIVATE KEY", bytes: X509.packPkcs1(jwk) }); + var sig = RSA.signSync(keypem, Enc.hexToBuf(request)); + return CSR.toDer({ request: request, signature: sig }); +}; +CSR.sign = function csrEcSig(jwk, request) { + var keypem = PEM.packBlock({ type: "RSA PRIVATE KEY", bytes: X509.packPkcs1(jwk) }); + return RSA.sign(keypem, Enc.hexToBuf(request)).then(function (sig) { + return CSR.toDer({ request: request, signature: sig }); + }); +}; +CSR.toDer = function encode(opts) { + var sty = ASN1('30' + // 1.2.840.113549.1.1.11 sha256WithRSAEncryption (PKCS #1) + , ASN1('06', '2a864886f70d01010b') + , ASN1('05') + ); + return ASN1('30' + // The Full CSR Request Body + , opts.request + // The Signature Type + , sty + // The Signature + , ASN1.BitStr(Enc.bufToHex(opts.signature)) + ); +}; + +// +// RSA +// + +// Took some tips from https://gist.github.com/codermapuche/da4f96cdb6d5ff53b7ebc156ec46a10a +RSA.signSync = function signRsaSync(keypem, ab) { + // Signer is a stream + var sign = crypto.createSign('SHA256'); + sign.write(new Uint8Array(ab)); + sign.end(); + + // The signature is ASN1 encoded, as it turns out + var sig = sign.sign(keypem); + + // Convert to a JavaScript ArrayBuffer just because + return new Uint8Array(sig.buffer.slice(sig.byteOffset, sig.byteOffset + sig.byteLength)); +}; +RSA.sign = function signRsa(keypem, ab) { + return Promise.resolve().then(function () { + return RSA.signSync(keypem, ab); + }); +}; diff --git a/express-server/node_modules/rsa-compat/lib/rsa-csr/lib/encoding.js b/express-server/node_modules/rsa-compat/lib/rsa-csr/lib/encoding.js new file mode 100644 index 00000000..f6b6ab0a --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rsa-csr/lib/encoding.js @@ -0,0 +1,34 @@ +'use strict'; + +var Enc = module.exports; + +Enc.base64ToHex = function base64ToHex(b64) { + return Buffer.from(b64, 'base64').toString('hex').toLowerCase(); +}; + +Enc.bufToBase64 = function bufToBase64(u8) { + // we want to maintain api compatability with browser APIs, + // so we assume that this could be a Uint8Array + return Buffer.from(u8).toString('base64'); +}; + +Enc.bufToHex = function toHex(u8) { + return Buffer.from(u8).toString('hex').toLowerCase(); +}; + +Enc.hexToBuf = function (hex) { + return Buffer.from(hex, 'hex'); +}; + +Enc.numToHex = function numToHex(d) { + d = d.toString(16); + if (d.length % 2) { + return '0' + d; + } + return d; +}; + +Enc.utf8ToHex = function utf8ToHex(str) { + // node can properly handle utf-8 strings + return Buffer.from(str).toString('hex').toLowerCase(); +}; diff --git a/express-server/node_modules/rsa-compat/lib/rsa-csr/lib/pem.js b/express-server/node_modules/rsa-compat/lib/rsa-csr/lib/pem.js new file mode 100644 index 00000000..fb08dcc9 --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rsa-csr/lib/pem.js @@ -0,0 +1,12 @@ +'use strict'; + +var Enc = require('./encoding.js'); +var PEM = module.exports; + +PEM.packBlock = function (opts) { + // TODO allow for headers? + return '-----BEGIN ' + opts.type + '-----\n' + + Enc.bufToBase64(opts.bytes).match(/.{1,64}/g).join('\n') + '\n' + + '-----END ' + opts.type + '-----' + ; +}; diff --git a/express-server/node_modules/rsa-compat/lib/rsa-csr/lib/telemetry.js b/express-server/node_modules/rsa-compat/lib/rsa-csr/lib/telemetry.js new file mode 100644 index 00000000..9623b775 --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rsa-csr/lib/telemetry.js @@ -0,0 +1,111 @@ +'use strict'; + +// We believe in a proactive approach to sustainable open source. +// As part of that we make it easy for you to opt-in to following our progress +// and we also stay up-to-date on telemetry such as operating system and node +// version so that we can focus our efforts where they'll have the greatest impact. +// +// Want to learn more about our Terms, Privacy Policy, and Mission? +// Check out https://therootcompany.com/legal/ + +var os = require('os'); +var crypto = require('crypto'); +var https = require('https'); +var pkg = require('../package.json'); + +// to help focus our efforts in the right places +var data = { + package: pkg.name +, version: pkg.version +, node: process.version +, arch: process.arch || os.arch() +, platform: process.platform || os.platform() +, release: os.release() +}; + +function addCommunityMember(opts) { + setTimeout(function () { + var req = https.request({ + hostname: 'api.therootcompany.com' + , port: 443 + , path: '/api/therootcompany.com/public/community' + , method: 'POST' + , headers: { 'Content-Type': 'application/json' } + }, function (resp) { + // let the data flow, so we can ignore it + resp.on('data', function () {}); + //resp.on('data', function (chunk) { console.log(chunk.toString()); }); + resp.on('error', function () { /*ignore*/ }); + //resp.on('error', function (err) { console.error(err); }); + }); + var obj = JSON.parse(JSON.stringify(data)); + obj.action = 'updates'; + try { + obj.ppid = ppid(obj.action); + } catch(e) { + // ignore + //console.error(e); + } + obj.name = opts.name || undefined; + obj.address = opts.email; + obj.community = 'node.js@therootcompany.com'; + + req.write(JSON.stringify(obj, 2, null)); + req.end(); + req.on('error', function () { /*ignore*/ }); + //req.on('error', function (err) { console.error(err); }); + }, 50); +} + +function ping(action) { + setTimeout(function () { + var req = https.request({ + hostname: 'api.therootcompany.com' + , port: 443 + , path: '/api/therootcompany.com/public/ping' + , method: 'POST' + , headers: { 'Content-Type': 'application/json' } + }, function (resp) { + // let the data flow, so we can ignore it + resp.on('data', function () { }); + //resp.on('data', function (chunk) { console.log(chunk.toString()); }); + resp.on('error', function () { /*ignore*/ }); + //resp.on('error', function (err) { console.error(err); }); + }); + var obj = JSON.parse(JSON.stringify(data)); + obj.action = action; + try { + obj.ppid = ppid(obj.action); + } catch(e) { + // ignore + //console.error(e); + } + + req.write(JSON.stringify(obj, 2, null)); + req.end(); + req.on('error', function (/*e*/) { /*console.error('req.error', e);*/ }); + }, 50); +} + +// to help identify unique installs without getting +// the personally identifiable info that we don't want +function ppid(action) { + var parts = [ action, data.package, data.version, data.node, data.arch, data.platform, data.release ]; + var ifaces = os.networkInterfaces(); + Object.keys(ifaces).forEach(function (ifname) { + if (/^en/.test(ifname) || /^eth/.test(ifname) || /^wl/.test(ifname)) { + if (ifaces[ifname] && ifaces[ifname].length) { + parts.push(ifaces[ifname][0].mac); + } + } + }); + return crypto.createHash('sha1').update(parts.join(',')).digest('base64'); +} + +module.exports.ping = ping; +module.exports.joinCommunity = addCommunityMember; + +if (require.main === module) { + ping('install'); + //addCommunityMember({ name: "AJ ONeal", email: 'coolaj86@gmail.com' }); +} diff --git a/express-server/node_modules/rsa-compat/lib/rsa-csr/lib/x509.js b/express-server/node_modules/rsa-compat/lib/rsa-csr/lib/x509.js new file mode 100644 index 00000000..33cb9c51 --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rsa-csr/lib/x509.js @@ -0,0 +1,66 @@ +'use strict'; + +var ASN1 = require('./asn1.js'); +var Enc = require('./encoding.js'); + +var X509 = module.exports; + +X509.packCsr = function (asn1pubkey, domains) { + return ASN1('30' + // Version (0) + , ASN1.UInt('00') + + // 2.5.4.3 commonName (X.520 DN component) + , ASN1('30', ASN1('31', ASN1('30', ASN1('06', '550403'), ASN1('0c', Enc.utf8ToHex(domains[0]))))) + + // Public Key (RSA or EC) + , asn1pubkey + + // Request Body + , ASN1('a0' + , ASN1('30' + // 1.2.840.113549.1.9.14 extensionRequest (PKCS #9 via CRMF) + , ASN1('06', '2a864886f70d01090e') + , ASN1('31' + , ASN1('30' + , ASN1('30' + // 2.5.29.17 subjectAltName (X.509 extension) + , ASN1('06', '551d11') + , ASN1('04' + , ASN1('30', domains.map(function (d) { + return ASN1('82', Enc.utf8ToHex(d)); + }).join('')))))))) + ); +}; + +X509.packPkcs1 = function (jwk) { + var n = ASN1.UInt(Enc.base64ToHex(jwk.n)); + var e = ASN1.UInt(Enc.base64ToHex(jwk.e)); + + if (!jwk.d) { + return Enc.hexToBuf(ASN1('30', n, e)); + } + + return Enc.hexToBuf(ASN1('30' + , ASN1.UInt('00') + , n + , e + , ASN1.UInt(Enc.base64ToHex(jwk.d)) + , ASN1.UInt(Enc.base64ToHex(jwk.p)) + , ASN1.UInt(Enc.base64ToHex(jwk.q)) + , ASN1.UInt(Enc.base64ToHex(jwk.dp)) + , ASN1.UInt(Enc.base64ToHex(jwk.dq)) + , ASN1.UInt(Enc.base64ToHex(jwk.qi)) + )); +}; + +X509.packCsrPublicKey = function (jwk) { + // Sequence the key + var n = ASN1.UInt(Enc.base64ToHex(jwk.n)); + var e = ASN1.UInt(Enc.base64ToHex(jwk.e)); + var asn1pub = ASN1('30', n, e); + //var asn1pub = X509.packPkcs1({ kty: jwk.kty, n: jwk.n, e: jwk.e }); + + // Add the CSR pub key header + return ASN1('30', ASN1('30', ASN1('06', '2a864886f70d010101'), ASN1('05')), ASN1.BitStr(asn1pub)); +}; diff --git a/express-server/node_modules/rsa-compat/lib/rsa.js b/express-server/node_modules/rsa-compat/lib/rsa.js new file mode 100644 index 00000000..d642cfd6 --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/rsa.js @@ -0,0 +1,213 @@ +// Copyright 2016-2018 AJ ONeal. All rights reserved +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +'use strict'; + +var RSA = module.exports; +RSA.utils = {}; + +try { + require('buffer-v6-polyfill'); +} catch(e) { + /* ignore */ +} + +var Rasha = require('./rasha'); +var RSACSR = require('./rsa-csr'); +var NOBJ = {}; +var DEFAULT_BITLEN = 2048; +var DEFAULT_EXPONENT = 0x10001; + +RSA.generateKeypair = function (options, cb, extra1, extra2) { + var length; + var exponent; + if ('function' === typeof extra2) { + length = options || DEFAULT_BITLEN; + exponent = cb || DEFAULT_EXPONENT; + options = extra1 || NOBJ; + cb = extra2; + } else { + if (!options) { options = NOBJ; } + length = options.bitlen || DEFAULT_BITLEN; + exponent = options.exp || DEFAULT_EXPONENT; + } + + try { + var keypair = require('./generate-privkey.js')(length, exponent); + keypair.thumbprint = RSA.thumbprint(keypair); + cb(null, keypair); + } catch(e) { + cb(e); + } +}; + +RSA.import = function (options) { + options = JSON.parse(JSON.stringify(options)); + + // Private Keys + if (options.privateKeyPem) { + if (!options.privateKeyJwk) { + options.privateKeyJwk = Rasha.importSync({ pem: options.privateKeyPem }); + } + } + if (options.privateKeyJwk) { + if (!options.privateKeyPem) { + options.privateKeyPem = Rasha.exportSync({ + jwk: options.privateKeyJwk + , format: options.format || 'pkcs1' + , encoding: options.encoding || 'pem' + }); + } + } + + // Public Keys + if (options.publicKeyPem || options.privateKeyPem) { + if (!options.publicKeyJwk) { + options.publicKeyJwk = Rasha.importSync({ + pem: options.publicKeyPem || options.privateKeyPem + , public: true + }); + } + } + if (options.publicKeyJwk || options.privateKeyJwk) { + if (!options.publicKeyPem) { + options.publicKeyPem = Rasha.exportSync({ + jwk: options.publicKeyJwk || options.privateKeyJwk + , format: options.format || 'pkcs1' + , encoding: options.encoding || 'pem' + , public: true + }); + } + } + if (!options.publicKeyPem) { + throw new Error("Error: no keys were present to import"); + } + + // Consistent CRLF + if (options.privateKeyPem) { + options.privateKeyPem = options.privateKeyPem + .trim().replace(/[\r\n]+/g, '\r\n') + '\r\n'; + } + options.publicKeyPem = options.publicKeyPem + .trim().replace(/[\r\n]+/g, '\r\n') + '\r\n'; + + // Thumbprint + if (!options.thumbprint) { + options.thumbprint = RSA._thumbprint(options); + } + + return options; +}; + +RSA.exportPrivatePem = function (keypair) { + keypair = RSA.import(keypair); + return keypair.privateKeyPem; +}; +RSA.exportPublicPem = function (keypair) { + keypair = RSA.import(keypair); + return keypair.publicKeyPem; +}; + +RSA.exportPrivateJwk = function (keypair) { + keypair = RSA.import(keypair); + return keypair.privateKeyJwk; +}; +RSA.exportPublicJwk = function (keypair) { + if (!keypair.publicKeyJwk) { + keypair = RSA.import(keypair); + } + return keypair.publicKeyJwk; +}; + +RSA.signJws = RSA.generateJws = RSA.generateSignatureJws = RSA.generateSignatureJwk = +function (keypair, header, protect, payload) { +// old (keypair, payload, nonce) + var nonce; + + keypair = RSA.import(keypair); + keypair.publicKeyJwk = RSA.exportPublicJwk(keypair); + + if ('string' === typeof protect || ('undefined' === typeof protect && 'undefined' === typeof payload)) { + console.warn("deprecation notice: new signature for signJws(keypair, header, protect, payload)"); + // old API + payload = header; + nonce = protect; + protect = undefined; + header = { + alg: "RS256" + , jwk: keypair.publicKeyJwk + }; + protect = { nonce: nonce }; + } + + // Compute JWS signature + var protectedHeader = ""; + if (protect) { + protectedHeader = JSON.stringify(protect); // { alg: prot.alg, nonce: prot.nonce, url: prot.url }); + } + var protected64 = RSA.utils.toWebsafeBase64(Buffer.from(protectedHeader).toString('base64')); + var payload64 = RSA.utils.toWebsafeBase64(payload.toString('base64')); + var raw = protected64 + "." + payload64; + var pem = RSA.exportPrivatePem(keypair); + var signer = require('crypto').createSign("RSA-SHA256"); + signer.update(raw); + + return { + header: header + , protected: protected64 + , payload: payload64 + , signature: signer.sign(pem, 'base64') + .replace(/\+/g, '-') + .replace(/\//g, '_') + .replace(/=/g, '') + }; +}; + +RSA.generateCsrPem = function (keypair, domains) { + keypair = RSA.import(keypair); + return RSACSR.sync({ jwk: keypair.privateKeyJwk, domains: domains }); +}; +RSA.generateCsrDer = function (keypair, domains) { + keypair = RSA.import(keypair); + return RSACSR.sync({ + jwk: keypair.privateKeyJwk + , domains: domains + , encoding: 'der' + }); +}; +RSA.generateCsrDerWeb64 =RSA.generateCsrWeb64 = function (keypair, names) { + var buf = RSA.generateCsrDer(keypair, names); + var b64 = buf.toString('base64'); + return RSA.utils.toWebsafeBase64(b64); +}; + +RSA._thumbprintInput = function (n, e) { + // #L147 const rsaThumbprintTemplate = `{"e":"%s","kty":"RSA","n":"%s"}` + return Buffer.from('{"e":"'+ e + '","kty":"RSA","n":"'+ n +'"}', 'ascii'); +}; +RSA._thumbprint = function (keypair) { + var publicKeyJwk = keypair.publicKeyJwk; + + if (!publicKeyJwk.e || !publicKeyJwk.n) { + throw new Error("You must provide an RSA jwk with 'e' and 'n' (the public components)"); + } + + var input = RSA._thumbprintInput(publicKeyJwk.n, publicKeyJwk.e); + var base64Digest = require('crypto').createHash('sha256').update(input).digest('base64'); + + return RSA.utils.toWebsafeBase64(base64Digest); +}; +RSA.thumbprint = function (keypair) { + if (!keypair.publicKeyJwk) { + keypair.publicKeyJwk = RSA.exportPublicJwk(keypair); + } + return RSA._thumbprint(keypair); +}; + +RSA.utils.toWebsafeBase64 = function (b64) { + return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g,""); +}; + +RSA.exportPrivateKey = RSA.exportPrivatePem; +RSA.exportPublicKey = RSA.exportPublicPem; diff --git a/express-server/node_modules/rsa-compat/lib/telemetry.js b/express-server/node_modules/rsa-compat/lib/telemetry.js new file mode 100644 index 00000000..9623b775 --- /dev/null +++ b/express-server/node_modules/rsa-compat/lib/telemetry.js @@ -0,0 +1,111 @@ +'use strict'; + +// We believe in a proactive approach to sustainable open source. +// As part of that we make it easy for you to opt-in to following our progress +// and we also stay up-to-date on telemetry such as operating system and node +// version so that we can focus our efforts where they'll have the greatest impact. +// +// Want to learn more about our Terms, Privacy Policy, and Mission? +// Check out https://therootcompany.com/legal/ + +var os = require('os'); +var crypto = require('crypto'); +var https = require('https'); +var pkg = require('../package.json'); + +// to help focus our efforts in the right places +var data = { + package: pkg.name +, version: pkg.version +, node: process.version +, arch: process.arch || os.arch() +, platform: process.platform || os.platform() +, release: os.release() +}; + +function addCommunityMember(opts) { + setTimeout(function () { + var req = https.request({ + hostname: 'api.therootcompany.com' + , port: 443 + , path: '/api/therootcompany.com/public/community' + , method: 'POST' + , headers: { 'Content-Type': 'application/json' } + }, function (resp) { + // let the data flow, so we can ignore it + resp.on('data', function () {}); + //resp.on('data', function (chunk) { console.log(chunk.toString()); }); + resp.on('error', function () { /*ignore*/ }); + //resp.on('error', function (err) { console.error(err); }); + }); + var obj = JSON.parse(JSON.stringify(data)); + obj.action = 'updates'; + try { + obj.ppid = ppid(obj.action); + } catch(e) { + // ignore + //console.error(e); + } + obj.name = opts.name || undefined; + obj.address = opts.email; + obj.community = 'node.js@therootcompany.com'; + + req.write(JSON.stringify(obj, 2, null)); + req.end(); + req.on('error', function () { /*ignore*/ }); + //req.on('error', function (err) { console.error(err); }); + }, 50); +} + +function ping(action) { + setTimeout(function () { + var req = https.request({ + hostname: 'api.therootcompany.com' + , port: 443 + , path: '/api/therootcompany.com/public/ping' + , method: 'POST' + , headers: { 'Content-Type': 'application/json' } + }, function (resp) { + // let the data flow, so we can ignore it + resp.on('data', function () { }); + //resp.on('data', function (chunk) { console.log(chunk.toString()); }); + resp.on('error', function () { /*ignore*/ }); + //resp.on('error', function (err) { console.error(err); }); + }); + var obj = JSON.parse(JSON.stringify(data)); + obj.action = action; + try { + obj.ppid = ppid(obj.action); + } catch(e) { + // ignore + //console.error(e); + } + + req.write(JSON.stringify(obj, 2, null)); + req.end(); + req.on('error', function (/*e*/) { /*console.error('req.error', e);*/ }); + }, 50); +} + +// to help identify unique installs without getting +// the personally identifiable info that we don't want +function ppid(action) { + var parts = [ action, data.package, data.version, data.node, data.arch, data.platform, data.release ]; + var ifaces = os.networkInterfaces(); + Object.keys(ifaces).forEach(function (ifname) { + if (/^en/.test(ifname) || /^eth/.test(ifname) || /^wl/.test(ifname)) { + if (ifaces[ifname] && ifaces[ifname].length) { + parts.push(ifaces[ifname][0].mac); + } + } + }); + return crypto.createHash('sha1').update(parts.join(',')).digest('base64'); +} + +module.exports.ping = ping; +module.exports.joinCommunity = addCommunityMember; + +if (require.main === module) { + ping('install'); + //addCommunityMember({ name: "AJ ONeal", email: 'coolaj86@gmail.com' }); +} diff --git a/express-server/node_modules/rsa-compat/package.json b/express-server/node_modules/rsa-compat/package.json new file mode 100644 index 00000000..ad55a5af --- /dev/null +++ b/express-server/node_modules/rsa-compat/package.json @@ -0,0 +1,108 @@ +{ + "_args": [ + [ + "rsa-compat@^1.5.0", + "/nodeapps/https-test/greenlock-express.js/node_modules/greenlock" + ] + ], + "_from": "rsa-compat@>=1.5.0 <2.0.0", + "_hasShrinkwrap": false, + "_id": "rsa-compat@1.9.0", + "_inCache": true, + "_installable": true, + "_location": "/rsa-compat", + "_nodeVersion": "10.13.0", + "_npmOperationalInternal": { + "host": "s3://npm-registry-packages", + "tmp": "tmp/rsa-compat_1.9.0_1544954189568_0.26195947533693653" + }, + "_npmUser": { + "email": "coolaj86@gmail.com", + "name": "coolaj86" + }, + "_npmVersion": "6.4.1", + "_phantomChildren": {}, + "_requested": { + "name": "rsa-compat", + "raw": "rsa-compat@^1.5.0", + "rawSpec": "^1.5.0", + "scope": null, + "spec": ">=1.5.0 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/acme-v2", + "/greenlock" + ], + "_resolved": "https://registry.npmjs.org/rsa-compat/-/rsa-compat-1.9.0.tgz", + "_shasum": "cd2ffd70d0a02f126342951bc809d40a18a4c0ce", + "_shrinkwrap": null, + "_spec": "rsa-compat@^1.5.0", + "_where": "/nodeapps/https-test/greenlock-express.js/node_modules/greenlock", + "author": { + "email": "coolaj86@gmail.com", + "name": "AJ ONeal", + "url": "https://coolaj86.com/" + }, + "bin": { + "rsa-keygen-js": "bin/rsa-keygen.js" + }, + "bugs": { + "url": "https://git.coolaj86.com/coolaj86/rsa-compat.js/issues" + }, + "dependencies": { + "node-forge": "^0.7.6", + "ursa-optional": "^0.9.10" + }, + "description": "RSA utils that work on Windows, Mac, and Linux with or without C compiler", + "devDependencies": {}, + "directories": {}, + "dist": { + "fileCount": 55, + "integrity": "sha512-0Qx/LE/n2ulCofM2H72CVBptMHcnUXZVKw7F1rOny+nFgTo2aEMFwVIEvS1WfnuT14U42RanuZEIzcYVScQcQA==", + "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcFiFOCRA9TVsSAnZWagAAzzsP/ig2SAoTOUMLTgRRTBVp\nXXjZ4tGbgaW86shjrzfibZzt44svlvggJad5m4zzc8Oatm36RDVLrgUwbLeQ\nVLInLWiIZX+wJP5ToV4vAwpjfGubFyhi9jbj9YBGw6XJ/zxGHcaLD2/m8Nec\nqemjPASLPhGAbPmDOsyfzDsuJlGiTI89ysBFpyEkpjz00si0ZDZhY4r/0ISB\nvfaWn0ISTnDRVCvYH8Y+BUuCYUCNP/jn2tiXd+18kuCwrIeHsLxk7+mz58NH\nFvQTpk02diP8erkWxRoggWwazXVhq5zQBp5S14BVdLPimgW8ViHv0YUfOrRe\nxn0J1B0M2I0pmkGX2ROBn8AmQExDmYR1BzS22euVxvByEsLMa2zQSxFjPzVG\nZ3kpCta4FHCRQqgau5jI8GAHvogET1w7cANL8di9kiHi18k5C2SbUTmkqSSt\n9/WTzsIfuC7pGI2t211WbEfO313B9hs27B6wkGOO379ckeveVYJryU27VNm6\nBiMt7zR36vR2hvuFUhBSieXjMGup9yfHKq225VcZZDZg07mtx4lK32hNVTG1\n0ZfC09RDcKip9AN2w7eyyw7wd9yWSmVC20wb7ppOVBIl6pfbcu67RyuJWmJ1\nzDA95/JPgtRc1Pl/s99y36dJ7PgThTWNSHi528oYFkek1240UH4vqupLM/du\nmYC3\r\n=b4p+\r\n-----END PGP SIGNATURE-----\r\n", + "shasum": "cd2ffd70d0a02f126342951bc809d40a18a4c0ce", + "tarball": "https://registry.npmjs.org/rsa-compat/-/rsa-compat-1.9.0.tgz", + "unpackedSize": 126979 + }, + "gitHead": "7580d700bfe9632abae30a4faefc2b3fd10b0b74", + "homepage": "https://git.coolaj86.com/coolaj86/rsa-compat.js#readme", + "keywords": [ + "RSA", + "certificate", + "forge", + "jwk", + "key", + "linux", + "mac", + "ssl", + "tls", + "ursa", + "windows" + ], + "license": "MPL-2.0", + "main": "index.js", + "maintainers": [ + { + "name": "coolaj86", + "email": "coolaj86@gmail.com" + } + ], + "name": "rsa-compat", + "optionalDependencies": { + "ursa-optional": "^0.9.10" + }, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "https://git.coolaj86.com/coolaj86/rsa-compat.js.git" + }, + "scripts": { + "postinstall": "node lib/telemetry.js event:install", + "test": "bash test.sh" + }, + "trulyOptionalDependencies": { + "buffer-v6-polyfill": "^1.0.3" + }, + "version": "1.9.0" +} diff --git a/express-server/node_modules/rsa-compat/test.sh b/express-server/node_modules/rsa-compat/test.sh new file mode 100644 index 00000000..27342ec8 --- /dev/null +++ b/express-server/node_modules/rsa-compat/test.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -e + +node tests/generate-csr.js +node tests/generate-key.js +node tests/generate-key-new.js +node tests/generate-sig.js +node tests/reciprocate.js diff --git a/express-server/node_modules/rsa-compat/tests/generate-csr.js b/express-server/node_modules/rsa-compat/tests/generate-csr.js new file mode 100644 index 00000000..f972ffae --- /dev/null +++ b/express-server/node_modules/rsa-compat/tests/generate-csr.js @@ -0,0 +1,26 @@ +'use strict'; + +var RSA = require('../').RSA; + +var keypair = { + privateKeyJwk: { + "kty": "RSA", + "n": "AMJubTfOtAarnJytLE8fhNsEI8wnpjRvBXGK/Kp0675J10ORzxyMLqzIZF3tcrUkKBrtdc79u4X0GocDUgukpfkY+2UPUS/GxehUYbYrJYWOLkoJWzxn7wfoo9X1JgvBMY6wHQnTKvnzZdkom2FMhGxkLaEUGDSfsNznTTZNBBg9", + "e": "AQAB", + "d": "HT8DCrv69G3n9uFNovE4yMEMqW7lX0m75eJkMze3Jj5xNOa/4qlrc+4IuuA2uuyfY72IVQRxqqqXOuvS8ZForZZk+kWSd6z45hrpbNAAHH2Rf7XwnwHY8VJrOQF3UtbktTWqHX36ITZb9Hmf18hWsIeEp8Ng7Ru9h7hNuVxKMjk=", + "p": "AONjOvZVAvhCM2JnLGWJG3+5Boar3MB5P4ezfExDmuyGET/w0C+PS60jbjB8TivQsSdEcGo7GOaOlmAX6EQtAec=", + "q": "ANrllgJsy4rTMfa3mQ50kMIcNahiEOearhAcJgQUCHuOjuEnhU9FfExA/m5FXjmEFQhRwkuhk0QaIqTGbUzxGDs=", + "dp": "ALuxHOpYIatqeZ+wKiVllx1GTOy8z+rQKnCI5wDMjQTPZU2yKSYY0g6IQFwlPyFLke8nvuLxBQzKhbWsBjzAKeE=", + "dq": "XLhDAmPzE6rBzy+VtXnKl247jEd9wZzTfh9uOuwBa9TG0Lhcz2cvb11YaH0ZnGNGRW/cTQzzxDUN1531TlIRYQ==", + "qi": "AI2apz6ECfGwhsvIcU3+yFt+3CA78CUVsX4NUul5m3Cls2m+5MbGQG5K0hGpxjDC3OmXTq1Y5gnep5yUZvVPZI4=" + } +}; + +var csrPem = RSA.generateCsrPem(keypair, ['example.com', 'www.example.com']); +var csr64 = RSA.generateCsrDerWeb64(keypair, ['example.com', 'www.example.com']); +console.log(''); +console.log('DEBUG csrPem'); +console.log(csrPem); +console.log(''); +console.log('DEBUG csr64'); +console.log(csr64); diff --git a/express-server/node_modules/rsa-compat/tests/generate-key-new.js b/express-server/node_modules/rsa-compat/tests/generate-key-new.js new file mode 100644 index 00000000..bc04e793 --- /dev/null +++ b/express-server/node_modules/rsa-compat/tests/generate-key-new.js @@ -0,0 +1,33 @@ +'use strict'; + +var RSA = require('../').RSA; + +RSA.generateKeypair(null, function (err, keys) { + if (!keys || !keys.privateKeyJwk) { + throw new Error("Expected privateKeyJwk, but it is missing"); + } + + var options = { + public: true // export public keys + , pem: true // export pems + , jwk: false // export jwks + , internal: true // preserve internal intermediate formats (_ursa, _forge) + //, thumbprint: true // JWK sha256 thumbprint + , bitlen: 2048 + , exp: 65537 + }; + RSA.generateKeypair(options, function (err, keys) { + if ( + (keys.publicKeyJwk && !keys.thumbprint) + || !keys.privateKeyPem + || !keys.publicKeyPem + //|| !keys.thumbprint + ) { + console.error(Object.keys(keys)); + throw new Error("Missing expected keys"); + } + + console.log('All is well!'); + }); + +}); diff --git a/express-server/node_modules/rsa-compat/tests/generate-key.js b/express-server/node_modules/rsa-compat/tests/generate-key.js new file mode 100644 index 00000000..3911ac9c --- /dev/null +++ b/express-server/node_modules/rsa-compat/tests/generate-key.js @@ -0,0 +1,31 @@ +'use strict'; + +var RSA = require('../').RSA; + +RSA.generateKeypair(null, null, null, function (err, keys) { + if (!keys.privateKeyJwk) { + throw new Error("Expected privateKeyJwk, but it is missing"); + } + + var options = { + public: true // export public keys + , pem: true // export pems + , jwk: false // export jwks + , internal: true // preserve internal intermediate formats (_ursa, _forge) + //, thumbprint: true // JWK sha256 thumbprint + }; + RSA.generateKeypair(512, 65537, options, function (err, keys) { + if ( + (keys.publicKeyJwk && !keys.thumbprint) + || !keys.privateKeyPem + || !keys.publicKeyPem + //|| !keys.thumbprint + ) { + console.error(Object.keys(keys)); + throw new Error("Missing expected keys"); + } + + console.log('All is well!'); + }); + +}); diff --git a/express-server/node_modules/rsa-compat/tests/generate-sig.js b/express-server/node_modules/rsa-compat/tests/generate-sig.js new file mode 100644 index 00000000..89a3b981 --- /dev/null +++ b/express-server/node_modules/rsa-compat/tests/generate-sig.js @@ -0,0 +1,54 @@ +'use strict'; + +var RSA = require('../').RSA; + +var keypair = { + privateKeyJwk: { + "kty": "RSA", + "n": "AMJubTfOtAarnJytLE8fhNsEI8wnpjRvBXGK_Kp0675J10ORzxyMLqzIZF3tcrUkKBrtdc79u4X0GocDUgukpfkY-2UPUS_GxehUYbYrJYWOLkoJWzxn7wfoo9X1JgvBMY6wHQnTKvnzZdkom2FMhGxkLaEUGDSfsNznTTZNBBg9", + "e": "AQAB", + "d": "HT8DCrv69G3n9uFNovE4yMEMqW7lX0m75eJkMze3Jj5xNOa_4qlrc-4IuuA2uuyfY72IVQRxqqqXOuvS8ZForZZk-kWSd6z45hrpbNAAHH2Rf7XwnwHY8VJrOQF3UtbktTWqHX36ITZb9Hmf18hWsIeEp8Ng7Ru9h7hNuVxKMjk=", + "p": "AONjOvZVAvhCM2JnLGWJG3-5Boar3MB5P4ezfExDmuyGET_w0C-PS60jbjB8TivQsSdEcGo7GOaOlmAX6EQtAec=", + "q": "ANrllgJsy4rTMfa3mQ50kMIcNahiEOearhAcJgQUCHuOjuEnhU9FfExA_m5FXjmEFQhRwkuhk0QaIqTGbUzxGDs=", + "dp": "ALuxHOpYIatqeZ-wKiVllx1GTOy8z-rQKnCI5wDMjQTPZU2yKSYY0g6IQFwlPyFLke8nvuLxBQzKhbWsBjzAKeE=", + "dq": "XLhDAmPzE6rBzy-VtXnKl247jEd9wZzTfh9uOuwBa9TG0Lhcz2cvb11YaH0ZnGNGRW_cTQzzxDUN1531TlIRYQ==", + "qi": "AI2apz6ECfGwhsvIcU3-yFt-3CA78CUVsX4NUul5m3Cls2m-5MbGQG5K0hGpxjDC3OmXTq1Y5gnep5yUZvVPZI4=" + } +}; + +/* +var ursaResult = { + "header": { + "alg": "RS256", + "jwk": { + "kty": "RSA", + "n": "AMJubTfOtAarnJytLE8fhNsEI8wnpjRvBXGK_Kp0675J10ORzxyMLqzIZF3tcrUkKBrtdc79u4X0GocDUgukpfkY-2UPUS_GxehUYbYrJYWOLkoJWzxn7wfoo9X1JgvBMY6wHQnTKvnzZdkom2FMhGxkLaEUGDSfsNznTTZNBBg9", + "e": "AQAB" + } + }, + "protected": "eyJub25jZSI6IjhlZjU2MjRmNWVjOWQzZWYifQ", + "payload": "JLzF1NBNCV3kfbJ5sFaFyX94fJuL2H-IzaoBN-ciiHk", + "signature": "Wb2al5SDyh5gjmkV79MK9m3sfNBBPjntSKor-34BBoGwr6n8qEnBmqB1Y4zbo-5rmvsoPmJsnRlP_hRiUY86zSAQyfbisTGrGBl0IQ7ditpkfYVm0rBWJ8WnYNqYNp8K3qcD7NW72tsy-XoWEjNlz4lWJeRdEG2Nt4CJgnREH4Y" +}; +var forgeResult = { + "header": { + "alg": "RS256", + "jwk": { + "kty": "RSA", + "n": "AMJubTfOtAarnJytLE8fhNsEI8wnpjRvBXGK_Kp0675J10ORzxyMLqzIZF3tcrUkKBrtdc79u4X0GocDUgukpfkY-2UPUS_GxehUYbYrJYWOLkoJWzxn7wfoo9X1JgvBMY6wHQnTKvnzZdkom2FMhGxkLaEUGDSfsNznTTZNBBg9", + "e": "AQAB" + } + }, + "protected": "eyJub25jZSI6IjhlZjU2MjRmNWVjOWQzZWYifQ", + "payload": "JLzF1NBNCV3kfbJ5sFaFyX94fJuL2H-IzaoBN-ciiHk", + "signature": "Wb2al5SDyh5gjmkV79MK9m3sfNBBPjntSKor-34BBoGwr6n8qEnBmqB1Y4zbo-5rmvsoPmJsnRlP_hRiUY86zSAQyfbisTGrGBl0IQ7ditpkfYVm0rBWJ8WnYNqYNp8K3qcD7NW72tsy-XoWEjNlz4lWJeRdEG2Nt4CJgnREH4Y" +}; +*/ + +var jws = RSA.signJws( + keypair +, Buffer.from('24bcc5d4d04d095de47db279b05685c97f787c9b8bd87f88cdaa0137e7228879', 'hex') +, '8ef5624f5ec9d3ef' +); + +console.log(JSON.stringify(jws, null, ' ')); diff --git a/express-server/node_modules/rsa-compat/tests/privkey.jwk b/express-server/node_modules/rsa-compat/tests/privkey.jwk new file mode 100644 index 00000000..fcda91ce --- /dev/null +++ b/express-server/node_modules/rsa-compat/tests/privkey.jwk @@ -0,0 +1 @@ +{"kty":"RSA","n":"sdk_fKUwpygZjNuAt7804KFBZoeBXtJ5cMZyRDRCmPNZRjOqXSdMTY7We7W103Ivs97hz--quMg-R8smv3F1-4Quyfm5vXFQWPxYdrsfJzPkyku4lY8uWbZ8N0X1CM61NgQHOAwe8eHOM0zd-MECxrBASBzLuiq6Df-GpsridFivMYlFj7UTXm92ReFyOXZUZacXneCVWyUMIU6Faj8h2UVpaCCNsopT0fRoqoBIJ-qeXhDpbvfLfhbb25p79msutxN7mpGW9a3wL1LyoCTpMLqIlZSWKKDVCNyoTS9RH7lch-j8_DtL9VfNTPv1rw-n-N-LQDQH6z5j7ZanXiek0Q","e":"AQAB","d":"pQuaej8Gpql1BJ4TlvHvzWJ4wgCQk4G5x2myUw84mp6Cw75gpLA6hGNBMm8QPRjjogX-Ay1EftT9zzx9Sf6uYepqTW_d6ivFR79vDUhcAdKLyRx6QPkuJ31NSzI10qWZz3XviRjegtRtunfkKtxbii24ifOHMM5D-Yef2xu_Cf5RRZVSipZdLRlgttSW2t-lXCaFN1-F8ITPCEqaQGoHn5fk9eEhl2sd3r8BCN1xp_KTAyqxBt9inDr__YlYynXS9Y35Wu4Ofn9CszwiCrZxezWO6Mn0-T-woDYj3jsO7aRvWPOIcMSaL7KqbM1BIWKPJqtSXqc8uVs4ZcVEnB4pXQ","p":"6sx1OM-3ise7cQCOffWLxbB8xNfpQSpyC0_ZzNF-FNSpCfFiJ6GjhBhgddppdyLD8jR34ZO4sTM6ny575ez6XOVrSUHi4Cavnv7DH8PxWT3_IVGKYKbqQt63KdIKpxxC3EoG66VPCQvjJ-TgkjNhqPLFKDW9ihvHVQlsDrVcLss","q":"wehZNfic8h69BUp8ynQIqSaao--N4fKm_fOH8kvmsZQlns0Asiy2jTYnfZy0jN380x_A8Q2Bx15N5byokRzn3NzC3dni_Z87h-c0Upss7G4iIPDngUwAN0EnraXbzVAv1jWC7wdsYJgSOLxJ0QVcLN-yPPs12ESf3hTQS2XNS1M","dp":"OWt0w0bw8Mx1h2YGcsFIxDir2ouerGQP7bpCXjdhKQD0sczJHz4FOfmoJUobfpoO5z1zj8PLZ_JKRMFeZVU1yOAGA61MKVrsmepdl3gYnqVtrh09xPMs2NuUWXLXThS4OR0VYi1UDbdNfuUXEknkeSedlX7G8m5mqeIa_eHWQE8","dq":"P7zGBi2QOS3NZ_3SAyIc7qzXy-ckNg7ywSrZltVIITrXGtm7ztVPtB8G4A0wc9VME4GuhA2yiPwAkvFuXzSnKjwOeanzKPa8NLHUywpiu9x_r2BAWInI0GDEUBnipBwlfT3dqgBAqYeTBb8ubFxcrgthpRXV3x6_hdpFlWMDFi0","qi":"FnwWA6Flj9jp2vy_RL1WEDTSr2xCdVm3guNuUhwXIav5-tXm5kDca-4fJEGUiSYzh_MLApUT9U-97zV5Qfws-OAq6pDu1-34hU-w1xpKh1OKvKEOfvYGX1mdzu3FIaaB7RQSr_TW3AyOl29HP--lOcrsYmIK5xnuqc13MQ6Nss4"} diff --git a/express-server/node_modules/rsa-compat/tests/privkey.pem b/express-server/node_modules/rsa-compat/tests/privkey.pem new file mode 100644 index 00000000..25f54f02 --- /dev/null +++ b/express-server/node_modules/rsa-compat/tests/privkey.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAsdk/fKUwpygZjNuAt7804KFBZoeBXtJ5cMZyRDRCmPNZRjOq +XSdMTY7We7W103Ivs97hz++quMg+R8smv3F1+4Quyfm5vXFQWPxYdrsfJzPkyku4 +lY8uWbZ8N0X1CM61NgQHOAwe8eHOM0zd+MECxrBASBzLuiq6Df+GpsridFivMYlF +j7UTXm92ReFyOXZUZacXneCVWyUMIU6Faj8h2UVpaCCNsopT0fRoqoBIJ+qeXhDp +bvfLfhbb25p79msutxN7mpGW9a3wL1LyoCTpMLqIlZSWKKDVCNyoTS9RH7lch+j8 +/DtL9VfNTPv1rw+n+N+LQDQH6z5j7ZanXiek0QIDAQABAoIBAQClC5p6PwamqXUE +nhOW8e/NYnjCAJCTgbnHabJTDzianoLDvmCksDqEY0EybxA9GOOiBf4DLUR+1P3P +PH1J/q5h6mpNb93qK8VHv28NSFwB0ovJHHpA+S4nfU1LMjXSpZnPde+JGN6C1G26 +d+Qq3FuKLbiJ84cwzkP5h5/bG78J/lFFlVKKll0tGWC21Jba36VcJoU3X4XwhM8I +SppAagefl+T14SGXax3evwEI3XGn8pMDKrEG32KcOv/9iVjKddL1jfla7g5+f0Kz +PCIKtnF7NY7oyfT5P7CgNiPeOw7tpG9Y84hwxJovsqpszUEhYo8mq1Jepzy5Wzhl +xUScHildAoGBAOrMdTjPt4rHu3EAjn31i8WwfMTX6UEqcgtP2czRfhTUqQnxYieh +o4QYYHXaaXciw/I0d+GTuLEzOp8ue+Xs+lzla0lB4uAmr57+wx/D8Vk9/yFRimCm +6kLetynSCqccQtxKBuulTwkL4yfk4JIzYajyxSg1vYobx1UJbA61XC7LAoGBAMHo +WTX4nPIevQVKfMp0CKkmmqPvjeHypv3zh/JL5rGUJZ7NALIsto02J32ctIzd/NMf +wPENgcdeTeW8qJEc59zcwt3Z4v2fO4fnNFKbLOxuIiDw54FMADdBJ62l281QL9Y1 +gu8HbGCYEji8SdEFXCzfsjz7NdhEn94U0EtlzUtTAoGAOWt0w0bw8Mx1h2YGcsFI +xDir2ouerGQP7bpCXjdhKQD0sczJHz4FOfmoJUobfpoO5z1zj8PLZ/JKRMFeZVU1 +yOAGA61MKVrsmepdl3gYnqVtrh09xPMs2NuUWXLXThS4OR0VYi1UDbdNfuUXEknk +eSedlX7G8m5mqeIa/eHWQE8CgYA/vMYGLZA5Lc1n/dIDIhzurNfL5yQ2DvLBKtmW +1UghOtca2bvO1U+0HwbgDTBz1UwTga6EDbKI/ACS8W5fNKcqPA55qfMo9rw0sdTL +CmK73H+vYEBYicjQYMRQGeKkHCV9Pd2qAECph5MFvy5sXFyuC2GlFdXfHr+F2kWV +YwMWLQKBgBZ8FgOhZY/Y6dr8v0S9VhA00q9sQnVZt4LjblIcFyGr+frV5uZA3Gvu +HyRBlIkmM4fzCwKVE/VPve81eUH8LPjgKuqQ7tft+IVPsNcaSodTiryhDn72Bl9Z +nc7txSGmge0UEq/01twMjpdvRz/vpTnK7GJiCucZ7qnNdzEOjbLO +-----END RSA PRIVATE KEY----- diff --git a/express-server/node_modules/rsa-compat/tests/reciprocate.js b/express-server/node_modules/rsa-compat/tests/reciprocate.js new file mode 100644 index 00000000..dc7a756f --- /dev/null +++ b/express-server/node_modules/rsa-compat/tests/reciprocate.js @@ -0,0 +1,86 @@ +'use strict'; + +var RSA = require('../').RSA; +var fs = require('fs'); +var path = require('path'); + +var privkeyPemRef = fs.readFileSync(path.join(__dirname, 'privkey.pem'), 'ascii'); +var privkeyJwkRef = JSON.parse(fs.readFileSync(path.join(__dirname, 'privkey.jwk'), 'ascii')); + +var refs = { + privPem: RSA.exportPrivatePem({ privateKeyJwk: privkeyJwkRef }) +, privJwk: RSA.exportPrivateJwk({ privateKeyPem: privkeyPemRef }) +}; + +var hasUrsa; +var imported; + +try { + hasUrsa = require('ursa') && true; +} catch(e) { + hasUrsa = false; +} + + + +// +// +// PEM tests +// +// +console.log('JWK -> PEM ?', privkeyPemRef === refs.privPem); +if (privkeyPemRef !== refs.privPem) { + // Watch out for tricky whitespaces (\n instead of \r\n, trailing \r\n, etc) + console.log('REF:'); + console.log(JSON.stringify(privkeyPemRef)); + console.log('GEN:'); + console.log(JSON.stringify(refs.privPem)); + throw new Error("Failed to validate importedJwk against referencePem"); +} + +console.log('PEM -> _ -> PEM ?', privkeyPemRef === refs.privPem); +if (hasUrsa) { + imported = RSA.import({ privateKeyPem: privkeyPemRef }); + refs.privPem2 = RSA.exportPrivatePem({ _ursa: imported._ursa }); +} +else { + imported = RSA.import({ privateKeyPem: privkeyPemRef }); + refs.privPem2 = RSA.exportPrivatePem(imported); +} +if (privkeyPemRef !== refs.privPem2) { + console.log('REF:'); + console.log(JSON.stringify(privkeyPemRef)); + console.log('GEN:'); + console.log(JSON.stringify(refs.privPem2)); + throw new Error("Failed to validate importedPem against referencePem"); +} + + +// +// +// JWK tests +// +// +console.log('PEM -> JWK ?', privkeyJwkRef.n === refs.privJwk.n); +if (![ 'kty', 'n', 'e', 'p', 'q', 'dp', 'dq', 'qi', 'd' ].every(function (k) { + return privkeyJwkRef[k] === refs.privJwk[k]; +})) { + console.log('REF:'); + console.log(privkeyJwkRef); + console.log('GEN:'); + console.log(refs.privJwk); + throw new Error("Failed to validate importedPem against referenceJwk"); +} + +imported = RSA.import({ privateKeyJwk: privkeyJwkRef }); +refs.privJwk2 = RSA.exportPrivateJwk(imported); +console.log('JWK -> _ -> JWK ?', privkeyJwkRef.n === refs.privJwk2.n); +if (privkeyJwkRef.n !== refs.privJwk2.n) { + console.log('REF:'); + console.log(privkeyJwkRef); + console.log('GEN:'); + console.log(refs.privJwk2); + throw new Error("Failed to validate importedJwk against referenceJwk"); +} + +console.log(''); diff --git a/express-server/node_modules/safe-replace/LICENSE b/express-server/node_modules/safe-replace/LICENSE new file mode 100644 index 00000000..8f71f43f --- /dev/null +++ b/express-server/node_modules/safe-replace/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/express-server/node_modules/safe-replace/README.md b/express-server/node_modules/safe-replace/README.md new file mode 100644 index 00000000..e60d24d1 --- /dev/null +++ b/express-server/node_modules/safe-replace/README.md @@ -0,0 +1,86 @@ +safe-replace +============ + +A micro-module for safely replacing a file. + +This is intended to be generally safe even when a function that writes a file +is accidentally called twice (as may happen with node cluster). + +Commandline Reference +--------------------- + +If I want to safely replace a file with a new version, I would do so like this: + +```bash +# create the new version +touch keep.txt.RANDOM.tmp + +# remove the previous backup +rm -f keep.txt.bak + +# move the current version to the backup +mv keep.txt keep.txt.bak + +# move the new version to the current +mv keep.txt.RANDOM.tmp keep.txt +``` + +If `keep.txt` became corrupt and I wanted to use the backup, +I would do this: + +```bash +# copy the backup to the new version +rsync keep.txt.bak keep.txt +``` + +In Node +------- + +I ported that proccess to node. + +``` +sfs.writeFileAsync +sfs.stageAsync +sfs.commitAsync +sfs.revertAsync +``` + +```js +// default behavior is to concat (filename + '.' + rnd() + '.tmp') +var safeReplace = require('safe-replace').create({ tmp: 'tmp', bak: 'bak' }); + +var data = new Buffer('A priceless document'); +safeReplace.writeFileAsync('keep.txt', data, 'ascii').then(function () { + fs.readdir('.', function (nodes) { + console.log('file system nodes', nodes); + // keep.txt + // keep.txt.bak + }); +}); + +// let's say I want to write a tmp file and not commit it... weird +safeReplace.stageAsync('keep.txt', data, 'ascii').then(function (tmpname) { + fs.readdir('.', function (nodes) { + console.log('file system nodes', nodes); + // keep.txt.ac71teh8mja.tmp + }); +}); + +// let's say I wrote keep.txt.x7t7sq926.tmp with my own mechanism +safeReplace.commitAsync('keep.txt.x7t7sq926.tmp', 'keep.txt').then(function () { + fs.readdir('.', function (nodes) { + console.log('file system nodes', nodes); + // keep.txt + // keep.txt.bak + }); +}); + +// let's say I want to revert the file from the '.bak' +safeReplace.revertAsync('keep.txt').then(function () { + fs.readdir('.', function (nodes) { + console.log('file system nodes', nodes); + // keep.txt + // keep.txt.bak + }); +}); +``` diff --git a/express-server/node_modules/safe-replace/index.js b/express-server/node_modules/safe-replace/index.js new file mode 100644 index 00000000..63240b2e --- /dev/null +++ b/express-server/node_modules/safe-replace/index.js @@ -0,0 +1,118 @@ +'use strict'; + +var PromiseA; +try { + PromiseA = require('bluebird'); +} catch(e) { + PromiseA = global.Promise; +} + +var util = require('util'); +var promisify = util.promisify || PromiseA.promisify; +if (!PromiseA || !promisify) { + throw new Error("DON'T PANIC. Everything is A-OK." + + " However, you're on a really old version of node. All you need to do is `npm install --save bluebird`" + + " (in your project directory, which is probably '" + require('path').dirname(require.main.filename) + "')" + + " and everything will work just fine."); +} + +var fs = require('fs'); +var writeFileAsync = promisify(fs.writeFile); +var unlinkAsync = promisify(fs.unlink); +var renameAsync = promisify(fs.rename); +var crypto = require('crypto'); + +function noop() { +} + +function create(options) { + + if (!options) { + options = {}; + } + if (!options.tmp) { + options.tmp = 'tmp'; + } + if (!options.bak) { + options.bak = 'bak'; + } + if (options.tmp === options.bak) { + throw new Error("'tmp' and 'bak' suffixes cannot be the same... duh"); + } + + var tmpnamefn = options.tmpnamefn || function (pathname) { + return pathname + '.' + crypto.randomBytes(8).toString('hex') + '.' + options.tmp; + }; + var baknamefn = options.baknamefn || function (pathname) { + return pathname + '.' + options.bak; + }; + /* + var namefn = options.namefn || function (pathname) { + return pathname; + }; + */ + + var sfs = { + writeFileAsync: function (filename, data, options) { + return sfs.stage(filename, data, options).then(function (tmpname) { + //console.log(filename); + return sfs.commit(tmpname, filename); + }); + } + , stageAsync: function (filename, data, options) { + var tmpname = tmpnamefn(filename); + //console.log(tmpname); + return writeFileAsync(tmpname, data, options).then(function () { + return tmpname; + }); + } + , commitAsync: function (tmpname, filename) { + var bakname = baknamefn(filename); + // this may not exist + return unlinkAsync(bakname).then(noop, noop).then(function () { + // this may not exist + //console.log(namefn(filename), '->', bakname); + return renameAsync(filename, bakname).then(function () { + //console.log('created bak'); + }, noop); + }).then(function () { + // this must be successful + //console.log(filename, '->', filename); + return renameAsync(tmpname, filename).then(noop, function (err) { + //console.error(err); + return sfs.revert(filename).then(function () { + return PromiseA.reject(err); + }); + }); + }); + } + , revertAsync: function (filename) { + return new PromiseA(function (resolve, reject) { + var bakname = baknamefn(filename); + var tmpname = tmpnamefn(filename); + + var reader = fs.createReadStream(bakname); + var writer = fs.createWriteStream(tmpname); + + reader.on('error', reject); + writer.on('error', reject); + + reader.pipe(writer); + writer.on('close', function () { + sfs.commit(tmpname, filename).then(resolve, reject); + }); + }); + } + , tmpnamefn: tmpnamefn + , baknamefn: baknamefn + , create: create + }; + sfs.writeFile = sfs.writeFileAsync; + sfs.stage = sfs.stageAsync; + sfs.commit = sfs.commitAsync; + sfs.revert = sfs.revertAsync; + + return sfs; +} + +module.exports = create(); diff --git a/express-server/node_modules/safe-replace/package.json b/express-server/node_modules/safe-replace/package.json new file mode 100644 index 00000000..377d062d --- /dev/null +++ b/express-server/node_modules/safe-replace/package.json @@ -0,0 +1,93 @@ +{ + "_args": [ + [ + "safe-replace@^1.0.3", + "/nodeapps/https-test/greenlock-express.js/node_modules/le-store-certbot" + ] + ], + "_from": "safe-replace@>=1.0.3 <2.0.0", + "_hasShrinkwrap": false, + "_id": "safe-replace@1.1.0", + "_inCache": true, + "_installable": true, + "_location": "/safe-replace", + "_nodeVersion": "10.6.0", + "_npmOperationalInternal": { + "host": "s3://npm-registry-packages", + "tmp": "tmp/safe-replace_1.1.0_1536002535947_0.38815297465919096" + }, + "_npmUser": { + "email": "coolaj86@gmail.com", + "name": "coolaj86" + }, + "_npmVersion": "6.1.0", + "_phantomChildren": {}, + "_requested": { + "name": "safe-replace", + "raw": "safe-replace@^1.0.3", + "rawSpec": "^1.0.3", + "scope": null, + "spec": ">=1.0.3 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/le-store-certbot", + "/pyconf" + ], + "_resolved": "https://registry.npmjs.org/safe-replace/-/safe-replace-1.1.0.tgz", + "_shasum": "432821b5a8139a38b534678d712f0850fe3e5235", + "_shrinkwrap": null, + "_spec": "safe-replace@^1.0.3", + "_where": "/nodeapps/https-test/greenlock-express.js/node_modules/le-store-certbot", + "author": { + "email": "coolaj86@gmail.com", + "name": "AJ ONeal", + "url": "https://coolaj86.com/" + }, + "bugs": { + "url": "https://git.coolaj86.com/coolaj86/fs-safe-replace.js/issues" + }, + "dependencies": {}, + "description": "A micro-module for safely replacing a file.", + "devDependencies": {}, + "directories": {}, + "dist": { + "fileCount": 5, + "integrity": "sha512-9/V2E0CDsKs9DWOOwJH7jYpSl9S3N05uyevNjvsnDauBqRowBPOyot1fIvV5N2IuZAbYyvrTXrYFVG0RZInfFw==", + "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbjYnoCRA9TVsSAnZWagAArVUP/RJ9pBsnGovUfM9Nt1JO\nkPW7FsKanVR3HAhQw0qRWOJiuSnr3cH/Z0SqwpRlSLWIZI1QV9yYsg9sPWZJ\nHd/xYjFdrgGPl6T4XW7GfF6CQTmJePjTD7cvwdR73qzxGRglUk9xjOrXsMAA\nrRm2yltVxqmbrdlqd5nxiw8JurwIjipH85lP+1RFaeraOtk9vrxzlHPIhPQo\nrOIa0ivDAGQxLwS58RVEBjxcJI2ZonnWBfKrR0CP+nQC9IHiNglGkRvTB1QW\nHKpp6Yis2mAQThddKENsT5Gx8M1Im8HFMGMmKi9jZPHT9A4wTv2/eRKmZIqV\n09X3gLjjAhWRx6AWc9H2luK+O0aUdoRWT6y2BJqkxOm2afHy4NIHo539RPAJ\nfx5qDkfD2LOaFbUN6Cr7/zMNsTcJjklAoWC/eQoSjB2dJ/GONtZs83F43QhJ\nyd9bYOU8AWl+FNDlw0+QWzWUk3aDVLXhw29DHyYWjW5vTAzL5RKIGQHxLv8e\nVwa7LFoLc6aAnBOOtouTtdxuJGkJztrewwG6GSITJ/gUg8IUfH9CpqQvF7hP\ncazgE+qBcdlSQbcBSkEK3Jp6NemwH8vzE3nA1hYxRRP+UdzEEbxgkOzGEzj3\nMY09g0PBMW09heBpqGfGbDTWv/zrs5BzbF6uCmDgszpI+rMTnuAkCmL/xvT8\nyhmk\r\n=BtfS\r\n-----END PGP SIGNATURE-----\r\n", + "shasum": "432821b5a8139a38b534678d712f0850fe3e5235", + "tarball": "https://registry.npmjs.org/safe-replace/-/safe-replace-1.1.0.tgz", + "unpackedSize": 17811 + }, + "gitHead": "54b295422952af449286827a1f7846a425961851", + "homepage": "https://git.coolaj86.com/coolaj86/fs-safe-replace.jse", + "keywords": [ + "cluster", + "condition", + "config", + "file", + "json", + "race", + "replace", + "write" + ], + "license": "(MIT OR Apache-2.0)", + "main": "index.js", + "maintainers": [ + { + "name": "coolaj86", + "email": "coolaj86@gmail.com" + } + ], + "name": "safe-replace", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "https://git.coolaj86.com/coolaj86/fs-safe-replace.js.git" + }, + "scripts": { + "test": "node test.js" + }, + "version": "1.1.0" +} diff --git a/express-server/node_modules/safe-replace/test.js b/express-server/node_modules/safe-replace/test.js new file mode 100644 index 00000000..caa86e11 --- /dev/null +++ b/express-server/node_modules/safe-replace/test.js @@ -0,0 +1,11 @@ +'use strict'; + +var safeReplace = require('./'); //.create(); +//var safeReplace = require('safe-replace').create(); +var fs = require('fs'); + +safeReplace.writeFile('keep.txt', 'my precious').then(function () { + fs.readdir('.', function (err, nodes) { + console.log('file system nodes', nodes); + }); +}); diff --git a/express-server/node_modules/serve-index/HISTORY.md b/express-server/node_modules/serve-index/HISTORY.md new file mode 100644 index 00000000..4bc7d1a8 --- /dev/null +++ b/express-server/node_modules/serve-index/HISTORY.md @@ -0,0 +1,305 @@ +1.9.1 / 2017-09-28 +================== + + * deps: accepts@~1.3.4 + - deps: mime-types@~2.1.16 + * deps: debug@2.6.9 + * deps: http-errors@~1.6.2 + - deps: depd@1.1.1 + * deps: mime-types@~2.1.17 + - Add new mime types + - deps: mime-db@~1.30.0 + * deps: parseurl@~1.3.2 + - perf: reduce overhead for full URLs + - perf: unroll the "fast-path" `RegExp` + +1.9.0 / 2017-05-25 +================== + + * Set `X-Content-Type-Options: nosniff` header + * deps: batch@0.6.1 + * deps: debug@2.6.8 + - Allow colors in workers + - Deprecated `DEBUG_FD` environment variable set to `3` or higher + - Fix `DEBUG_MAX_ARRAY_LENGTH` + - Fix error when running under React Native + - Use same color for same namespace + - deps: ms@2.0.0 + * deps: http-errors@~1.6.1 + - Make `message` property enumerable for `HttpError`s + - deps: inherits@2.0.3 + - deps: setprototypeof@1.0.3 + - deps: statuses@'>= 1.3.1 < 2' + * deps: mime-types@~2.1.15 + - Add new mime types + - Add `audio/mp3` + +1.8.0 / 2016-06-17 +================== + + * Make inline file search case-insensitive + * deps: accepts@~1.3.3 + - deps: mime-types@~2.1.11 + - deps: negotiator@0.6.1 + - perf: improve header parsing speed + * deps: http-errors@~1.5.0 + - Use `setprototypeof` module to replace `__proto__` setting + - deps: inherits@2.0.1 + - deps: statuses@'>= 1.3.0 < 2' + - perf: enable strict mode + * deps: mime-types@~2.1.11 + - Add new mime types + - Update primary extension for `audio/mp4` + - deps: mime-db@~1.23.0 + +1.7.3 / 2016-01-24 +================== + + * deps: accepts@~1.2.13 + - deps: mime-types@~2.1.6 + * deps: batch@0.5.3 + - Fix invalid dependency for browserify + * deps: escape-html@~1.0.3 + - perf: enable strict mode + - perf: optimize string replacement + - perf: use faster string coercion + * deps: mime-types@~2.1.9 + - Add new mime types + * deps: parseurl@~1.3.1 + - perf: enable strict mode + +1.7.2 / 2015-07-30 +================== + + * deps: accepts@~1.2.12 + - deps: mime-types@~2.1.4 + * deps: mime-types@~2.1.4 + - Add new mime types + +1.7.1 / 2015-07-05 +================== + + * deps: accepts@~1.2.10 + - deps: mime-types@~2.1.2 + * deps: mime-types@~2.1.2 + - Add new mime types + +1.7.0 / 2015-06-15 +================== + + * Accept `function` value for `template` option + * Send non-chunked response for `OPTIONS` + * Stat parent directory when necessary + * Use `Date.prototype.toLocaleDateString` to format date + * deps: accepts@~1.2.9 + - deps: mime-types@~2.1.1 + - deps: negotiator@0.5.3 + - perf: avoid argument reassignment & argument slice + - perf: avoid negotiator recursive construction + - perf: enable strict mode + - perf: remove unnecessary bitwise operator + * deps: escape-html@1.0.2 + * deps: mime-types@~2.1.1 + - Add new mime types + * perf: enable strict mode + * perf: remove argument reassignment + +1.6.4 / 2015-05-12 +================== + + * deps: accepts@~1.2.7 + - deps: mime-types@~2.0.11 + - deps: negotiator@0.5.3 + * deps: debug@~2.2.0 + - deps: ms@0.7.1 + * deps: mime-types@~2.0.11 + - Add new mime types + +1.6.3 / 2015-03-13 +================== + + * Properly escape file names in HTML + * deps: accepts@~1.2.5 + - deps: mime-types@~2.0.10 + * deps: debug@~2.1.3 + - Fix high intensity foreground color for bold + - deps: ms@0.7.0 + * deps: escape-html@1.0.1 + * deps: mime-types@~2.0.10 + - Add new mime types + +1.6.2 / 2015-02-16 +================== + + * deps: accepts@~1.2.4 + - deps: mime-types@~2.0.9 + - deps: negotiator@0.5.1 + * deps: http-errors@~1.3.1 + - Construct errors using defined constructors from `createError` + - Fix error names that are not identifiers + - Set a meaningful `name` property on constructed errors + * deps: mime-types@~2.0.9 + - Add new mime types + - deps: mime-db@~1.7.0 + +1.6.1 / 2015-01-31 +================== + + * deps: accepts@~1.2.3 + - deps: mime-types@~2.0.8 + * deps: mime-types@~2.0.8 + - Add new mime types + - deps: mime-db@~1.6.0 + +1.6.0 / 2015-01-01 +================== + + * Add link to root directory + * deps: accepts@~1.2.2 + - deps: mime-types@~2.0.7 + - deps: negotiator@0.5.0 + * deps: batch@0.5.2 + * deps: debug@~2.1.1 + * deps: mime-types@~2.0.7 + - Add new mime types + - Fix missing extensions + - Fix various invalid MIME type entries + - Remove example template MIME types + - deps: mime-db@~1.5.0 + +1.5.3 / 2014-12-10 +================== + + * deps: accepts@~1.1.4 + - deps: mime-types@~2.0.4 + * deps: http-errors@~1.2.8 + - Fix stack trace from exported function + * deps: mime-types@~2.0.4 + - Add new mime types + - deps: mime-db@~1.3.0 + +1.5.2 / 2014-12-03 +================== + + * Fix icon name background alignment on mobile view + +1.5.1 / 2014-11-22 +================== + + * deps: accepts@~1.1.3 + - deps: mime-types@~2.0.3 + * deps: mime-types@~2.0.3 + - Add new mime types + - deps: mime-db@~1.2.0 + +1.5.0 / 2014-10-16 +================== + + * Create errors with `http-errors` + * deps: debug@~2.1.0 + - Implement `DEBUG_FD` env variable support + * deps: mime-types@~2.0.2 + - deps: mime-db@~1.1.0 + +1.4.1 / 2014-10-15 +================== + + * deps: accepts@~1.1.2 + - Fix error when media type has invalid parameter + - deps: negotiator@0.4.9 + +1.4.0 / 2014-10-03 +================== + + * Add `dir` argument to `filter` function + * Support using tokens multiple times + +1.3.1 / 2014-10-01 +================== + + * Fix incorrect 403 on Windows and Node.js 0.11 + * deps: accepts@~1.1.1 + - deps: mime-types@~2.0.2 + - deps: negotiator@0.4.8 + +1.3.0 / 2014-09-20 +================== + + * Add icon for mkv files + * Lookup icon by mime type for greater icon support + +1.2.1 / 2014-09-05 +================== + + * deps: accepts@~1.1.0 + * deps: debug@~2.0.0 + +1.2.0 / 2014-08-25 +================== + + * Add `debug` messages + * Resolve relative paths at middleware setup + +1.1.6 / 2014-08-10 +================== + + * Fix URL parsing + * deps: parseurl@~1.3.0 + +1.1.5 / 2014-07-27 +================== + + * Fix Content-Length calculation for multi-byte file names + * deps: accepts@~1.0.7 + - deps: negotiator@0.4.7 + +1.1.4 / 2014-06-20 +================== + + * deps: accepts@~1.0.5 + +1.1.3 / 2014-06-20 +================== + + * deps: accepts@~1.0.4 + - use `mime-types` + +1.1.2 / 2014-06-19 +================== + + * deps: batch@0.5.1 + +1.1.1 / 2014-06-11 +================== + + * deps: accepts@1.0.3 + +1.1.0 / 2014-05-29 +================== + + * Fix content negotiation when no `Accept` header + * Properly support all HTTP methods + * Support vanilla node.js http servers + * Treat `ENAMETOOLONG` as code 414 + * Use accepts for negotiation + +1.0.3 / 2014-05-20 +================== + + * Fix error from non-statable files in HTML view + +1.0.2 / 2014-04-28 +================== + + * Add `stylesheet` option + * deps: negotiator@0.4.3 + +1.0.1 / 2014-03-05 +================== + + * deps: negotiator@0.4.2 + +1.0.0 / 2014-03-05 +================== + + * Genesis from connect diff --git a/express-server/node_modules/serve-index/LICENSE b/express-server/node_modules/serve-index/LICENSE new file mode 100644 index 00000000..d8cce679 --- /dev/null +++ b/express-server/node_modules/serve-index/LICENSE @@ -0,0 +1,25 @@ +(The MIT License) + +Copyright (c) 2010 Sencha Inc. +Copyright (c) 2011 LearnBoost +Copyright (c) 2011 TJ Holowaychuk +Copyright (c) 2014-2015 Douglas Christopher Wilson + +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/express-server/node_modules/serve-index/README.md b/express-server/node_modules/serve-index/README.md new file mode 100644 index 00000000..c21db282 --- /dev/null +++ b/express-server/node_modules/serve-index/README.md @@ -0,0 +1,154 @@ +# serve-index + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Linux Build][travis-image]][travis-url] +[![Windows Build][appveyor-image]][appveyor-url] +[![Test Coverage][coveralls-image]][coveralls-url] +[![Gratipay][gratipay-image]][gratipay-url] + + Serves pages that contain directory listings for a given path. + +## Install + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```sh +$ npm install serve-index +``` + +## API + +```js +var serveIndex = require('serve-index') +``` + +### serveIndex(path, options) + +Returns middlware that serves an index of the directory in the given `path`. + +The `path` is based off the `req.url` value, so a `req.url` of `'/some/dir` +with a `path` of `'public'` will look at `'public/some/dir'`. If you are using +something like `express`, you can change the URL "base" with `app.use` (see +the express example). + +#### Options + +Serve index accepts these properties in the options object. + +##### filter + +Apply this filter function to files. Defaults to `false`. The `filter` function +is called for each file, with the signature `filter(filename, index, files, dir)` +where `filename` is the name of the file, `index` is the array index, `files` is +the array of files and `dir` is the absolute path the file is located (and thus, +the directory the listing is for). + +##### hidden + +Display hidden (dot) files. Defaults to `false`. + +##### icons + +Display icons. Defaults to `false`. + +##### stylesheet + +Optional path to a CSS stylesheet. Defaults to a built-in stylesheet. + +##### template + +Optional path to an HTML template or a function that will render a HTML +string. Defaults to a built-in template. + +When given a string, the string is used as a file path to load and then the +following tokens are replaced in templates: + + * `{directory}` with the name of the directory. + * `{files}` with the HTML of an unordered list of file links. + * `{linked-path}` with the HTML of a link to the directory. + * `{style}` with the specified stylesheet and embedded images. + +When given as a function, the function is called as `template(locals, callback)` +and it needs to invoke `callback(error, htmlString)`. The following are the +provided locals: + + * `directory` is the directory being displayed (where `/` is the root). + * `displayIcons` is a Boolean for if icons should be rendered or not. + * `fileList` is a sorted array of files in the directory. The array contains + objects with the following properties: + - `name` is the relative name for the file. + - `stat` is a `fs.Stats` object for the file. + * `path` is the full filesystem path to `directory`. + * `style` is the default stylesheet or the contents of the `stylesheet` option. + * `viewName` is the view name provided by the `view` option. + +##### view + +Display mode. `tiles` and `details` are available. Defaults to `tiles`. + +## Examples + +### Serve directory indexes with vanilla node.js http server + +```js +var finalhandler = require('finalhandler') +var http = require('http') +var serveIndex = require('serve-index') +var serveStatic = require('serve-static') + +// Serve directory indexes for public/ftp folder (with icons) +var index = serveIndex('public/ftp', {'icons': true}) + +// Serve up public/ftp folder files +var serve = serveStatic('public/ftp') + +// Create server +var server = http.createServer(function onRequest(req, res){ + var done = finalhandler(req, res) + serve(req, res, function onNext(err) { + if (err) return done(err) + index(req, res, done) + }) +}) + +// Listen +server.listen(3000) +``` + +### Serve directory indexes with express + +```js +var express = require('express') +var serveIndex = require('serve-index') + +var app = express() + +// Serve URLs like /ftp/thing as public/ftp/thing +// The express.static serves the file contents +// The serveIndex is this module serving the directory +app.use('/ftp', express.static('public/ftp'), serveIndex('public/ftp', {'icons': true})) + +// Listen +app.listen(3000) +``` + +## License + +[MIT](LICENSE). The [Silk](http://www.famfamfam.com/lab/icons/silk/) icons +are created by/copyright of [FAMFAMFAM](http://www.famfamfam.com/). + +[npm-image]: https://img.shields.io/npm/v/serve-index.svg +[npm-url]: https://npmjs.org/package/serve-index +[travis-image]: https://img.shields.io/travis/expressjs/serve-index/master.svg?label=linux +[travis-url]: https://travis-ci.org/expressjs/serve-index +[appveyor-image]: https://img.shields.io/appveyor/ci/dougwilson/serve-index/master.svg?label=windows +[appveyor-url]: https://ci.appveyor.com/project/dougwilson/serve-index +[coveralls-image]: https://img.shields.io/coveralls/expressjs/serve-index/master.svg +[coveralls-url]: https://coveralls.io/r/expressjs/serve-index?branch=master +[downloads-image]: https://img.shields.io/npm/dm/serve-index.svg +[downloads-url]: https://npmjs.org/package/serve-index +[gratipay-image]: https://img.shields.io/gratipay/dougwilson.svg +[gratipay-url]: https://www.gratipay.com/dougwilson/ diff --git a/express-server/node_modules/serve-index/index.js b/express-server/node_modules/serve-index/index.js new file mode 100644 index 00000000..e3a619f9 --- /dev/null +++ b/express-server/node_modules/serve-index/index.js @@ -0,0 +1,646 @@ +/*! + * serve-index + * Copyright(c) 2011 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict'; + +/** + * Module dependencies. + * @private + */ + +var accepts = require('accepts'); +var createError = require('http-errors'); +var debug = require('debug')('serve-index'); +var escapeHtml = require('escape-html'); +var fs = require('fs') + , path = require('path') + , normalize = path.normalize + , sep = path.sep + , extname = path.extname + , join = path.join; +var Batch = require('batch'); +var mime = require('mime-types'); +var parseUrl = require('parseurl'); +var resolve = require('path').resolve; + +/** + * Module exports. + * @public + */ + +module.exports = serveIndex; + +/*! + * Icon cache. + */ + +var cache = {}; + +/*! + * Default template. + */ + +var defaultTemplate = join(__dirname, 'public', 'directory.html'); + +/*! + * Stylesheet. + */ + +var defaultStylesheet = join(__dirname, 'public', 'style.css'); + +/** + * Media types and the map for content negotiation. + */ + +var mediaTypes = [ + 'text/html', + 'text/plain', + 'application/json' +]; + +var mediaType = { + 'text/html': 'html', + 'text/plain': 'plain', + 'application/json': 'json' +}; + +/** + * Serve directory listings with the given `root` path. + * + * See Readme.md for documentation of options. + * + * @param {String} root + * @param {Object} options + * @return {Function} middleware + * @public + */ + +function serveIndex(root, options) { + var opts = options || {}; + + // root required + if (!root) { + throw new TypeError('serveIndex() root path required'); + } + + // resolve root to absolute and normalize + var rootPath = normalize(resolve(root) + sep); + + var filter = opts.filter; + var hidden = opts.hidden; + var icons = opts.icons; + var stylesheet = opts.stylesheet || defaultStylesheet; + var template = opts.template || defaultTemplate; + var view = opts.view || 'tiles'; + + return function (req, res, next) { + if (req.method !== 'GET' && req.method !== 'HEAD') { + res.statusCode = 'OPTIONS' === req.method ? 200 : 405; + res.setHeader('Allow', 'GET, HEAD, OPTIONS'); + res.setHeader('Content-Length', '0'); + res.end(); + return; + } + + // parse URLs + var url = parseUrl(req); + var originalUrl = parseUrl.original(req); + var dir = decodeURIComponent(url.pathname); + var originalDir = decodeURIComponent(originalUrl.pathname); + + // join / normalize from root dir + var path = normalize(join(rootPath, dir)); + + // null byte(s), bad request + if (~path.indexOf('\0')) return next(createError(400)); + + // malicious path + if ((path + sep).substr(0, rootPath.length) !== rootPath) { + debug('malicious path "%s"', path); + return next(createError(403)); + } + + // determine ".." display + var showUp = normalize(resolve(path) + sep) !== rootPath; + + // check if we have a directory + debug('stat "%s"', path); + fs.stat(path, function(err, stat){ + if (err && err.code === 'ENOENT') { + return next(); + } + + if (err) { + err.status = err.code === 'ENAMETOOLONG' + ? 414 + : 500; + return next(err); + } + + if (!stat.isDirectory()) return next(); + + // fetch files + debug('readdir "%s"', path); + fs.readdir(path, function(err, files){ + if (err) return next(err); + if (!hidden) files = removeHidden(files); + if (filter) files = files.filter(function(filename, index, list) { + return filter(filename, index, list, path); + }); + files.sort(); + + // content-negotiation + var accept = accepts(req); + var type = accept.type(mediaTypes); + + // not acceptable + if (!type) return next(createError(406)); + serveIndex[mediaType[type]](req, res, files, next, originalDir, showUp, icons, path, view, template, stylesheet); + }); + }); + }; +}; + +/** + * Respond with text/html. + */ + +serveIndex.html = function _html(req, res, files, next, dir, showUp, icons, path, view, template, stylesheet) { + var render = typeof template !== 'function' + ? createHtmlRender(template) + : template + + if (showUp) { + files.unshift('..'); + } + + // stat all files + stat(path, files, function (err, stats) { + if (err) return next(err); + + // combine the stats into the file list + var fileList = files.map(function (file, i) { + return { name: file, stat: stats[i] }; + }); + + // sort file list + fileList.sort(fileSort); + + // read stylesheet + fs.readFile(stylesheet, 'utf8', function (err, style) { + if (err) return next(err); + + // create locals for rendering + var locals = { + directory: dir, + displayIcons: Boolean(icons), + fileList: fileList, + path: path, + style: style, + viewName: view + }; + + // render html + render(locals, function (err, body) { + if (err) return next(err); + send(res, 'text/html', body) + }); + }); + }); +}; + +/** + * Respond with application/json. + */ + +serveIndex.json = function _json(req, res, files) { + send(res, 'application/json', JSON.stringify(files)) +}; + +/** + * Respond with text/plain. + */ + +serveIndex.plain = function _plain(req, res, files) { + send(res, 'text/plain', (files.join('\n') + '\n')) +}; + +/** + * Map html `files`, returning an html unordered list. + * @private + */ + +function createHtmlFileList(files, dir, useIcons, view) { + var html = '
    ' + + (view == 'details' ? ( + '
  • ' + + 'Name' + + 'Size' + + 'Modified' + + '
  • ') : ''); + + html += files.map(function (file) { + var classes = []; + var isDir = file.stat && file.stat.isDirectory(); + var path = dir.split('/').map(function (c) { return encodeURIComponent(c); }); + + if (useIcons) { + classes.push('icon'); + + if (isDir) { + classes.push('icon-directory'); + } else { + var ext = extname(file.name); + var icon = iconLookup(file.name); + + classes.push('icon'); + classes.push('icon-' + ext.substring(1)); + + if (classes.indexOf(icon.className) === -1) { + classes.push(icon.className); + } + } + } + + path.push(encodeURIComponent(file.name)); + + var date = file.stat && file.name !== '..' + ? file.stat.mtime.toLocaleDateString() + ' ' + file.stat.mtime.toLocaleTimeString() + : ''; + var size = file.stat && !isDir + ? file.stat.size + : ''; + + return '
  • ' + + '' + escapeHtml(file.name) + '' + + '' + escapeHtml(size) + '' + + '' + escapeHtml(date) + '' + + '
  • '; + }).join('\n'); + + html += '
'; + + return html; +} + +/** + * Create function to render html. + */ + +function createHtmlRender(template) { + return function render(locals, callback) { + // read template + fs.readFile(template, 'utf8', function (err, str) { + if (err) return callback(err); + + var body = str + .replace(/\{style\}/g, locals.style.concat(iconStyle(locals.fileList, locals.displayIcons))) + .replace(/\{files\}/g, createHtmlFileList(locals.fileList, locals.directory, locals.displayIcons, locals.viewName)) + .replace(/\{directory\}/g, escapeHtml(locals.directory)) + .replace(/\{linked-path\}/g, htmlPath(locals.directory)); + + callback(null, body); + }); + }; +} + +/** + * Sort function for with directories first. + */ + +function fileSort(a, b) { + // sort ".." to the top + if (a.name === '..' || b.name === '..') { + return a.name === b.name ? 0 + : a.name === '..' ? -1 : 1; + } + + return Number(b.stat && b.stat.isDirectory()) - Number(a.stat && a.stat.isDirectory()) || + String(a.name).toLocaleLowerCase().localeCompare(String(b.name).toLocaleLowerCase()); +} + +/** + * Map html `dir`, returning a linked path. + */ + +function htmlPath(dir) { + var parts = dir.split('/'); + var crumb = new Array(parts.length); + + for (var i = 0; i < parts.length; i++) { + var part = parts[i]; + + if (part) { + parts[i] = encodeURIComponent(part); + crumb[i] = '' + escapeHtml(part) + ''; + } + } + + return crumb.join(' / '); +} + +/** + * Get the icon data for the file name. + */ + +function iconLookup(filename) { + var ext = extname(filename); + + // try by extension + if (icons[ext]) { + return { + className: 'icon-' + ext.substring(1), + fileName: icons[ext] + }; + } + + var mimetype = mime.lookup(ext); + + // default if no mime type + if (mimetype === false) { + return { + className: 'icon-default', + fileName: icons.default + }; + } + + // try by mime type + if (icons[mimetype]) { + return { + className: 'icon-' + mimetype.replace('/', '-'), + fileName: icons[mimetype] + }; + } + + var suffix = mimetype.split('+')[1]; + + if (suffix && icons['+' + suffix]) { + return { + className: 'icon-' + suffix, + fileName: icons['+' + suffix] + }; + } + + var type = mimetype.split('/')[0]; + + // try by type only + if (icons[type]) { + return { + className: 'icon-' + type, + fileName: icons[type] + }; + } + + return { + className: 'icon-default', + fileName: icons.default + }; +} + +/** + * Load icon images, return css string. + */ + +function iconStyle(files, useIcons) { + if (!useIcons) return ''; + var i; + var list = []; + var rules = {}; + var selector; + var selectors = {}; + var style = ''; + + for (i = 0; i < files.length; i++) { + var file = files[i]; + + var isDir = file.stat && file.stat.isDirectory(); + var icon = isDir + ? { className: 'icon-directory', fileName: icons.folder } + : iconLookup(file.name); + var iconName = icon.fileName; + + selector = '#files .' + icon.className + ' .name'; + + if (!rules[iconName]) { + rules[iconName] = 'background-image: url(data:image/png;base64,' + load(iconName) + ');' + selectors[iconName] = []; + list.push(iconName); + } + + if (selectors[iconName].indexOf(selector) === -1) { + selectors[iconName].push(selector); + } + } + + for (i = 0; i < list.length; i++) { + iconName = list[i]; + style += selectors[iconName].join(',\n') + ' {\n ' + rules[iconName] + '\n}\n'; + } + + return style; +} + +/** + * Load and cache the given `icon`. + * + * @param {String} icon + * @return {String} + * @api private + */ + +function load(icon) { + if (cache[icon]) return cache[icon]; + return cache[icon] = fs.readFileSync(__dirname + '/public/icons/' + icon, 'base64'); +} + +/** + * Normalizes the path separator from system separator + * to URL separator, aka `/`. + * + * @param {String} path + * @return {String} + * @api private + */ + +function normalizeSlashes(path) { + return path.split(sep).join('/'); +}; + +/** + * Filter "hidden" `files`, aka files + * beginning with a `.`. + * + * @param {Array} files + * @return {Array} + * @api private + */ + +function removeHidden(files) { + return files.filter(function(file){ + return '.' != file[0]; + }); +} + +/** + * Send a response. + * @private + */ + +function send (res, type, body) { + // security header for content sniffing + res.setHeader('X-Content-Type-Options', 'nosniff') + + // standard headers + res.setHeader('Content-Type', type + '; charset=utf-8') + res.setHeader('Content-Length', Buffer.byteLength(body, 'utf8')) + + // body + res.end(body, 'utf8') +} + +/** + * Stat all files and return array of stat + * in same order. + */ + +function stat(dir, files, cb) { + var batch = new Batch(); + + batch.concurrency(10); + + files.forEach(function(file){ + batch.push(function(done){ + fs.stat(join(dir, file), function(err, stat){ + if (err && err.code !== 'ENOENT') return done(err); + + // pass ENOENT as null stat, not error + done(null, stat || null); + }); + }); + }); + + batch.end(cb); +} + +/** + * Icon map. + */ + +var icons = { + // base icons + 'default': 'page_white.png', + 'folder': 'folder.png', + + // generic mime type icons + 'image': 'image.png', + 'text': 'page_white_text.png', + 'video': 'film.png', + + // generic mime suffix icons + '+json': 'page_white_code.png', + '+xml': 'page_white_code.png', + '+zip': 'box.png', + + // specific mime type icons + 'application/font-woff': 'font.png', + 'application/javascript': 'page_white_code_red.png', + 'application/json': 'page_white_code.png', + 'application/msword': 'page_white_word.png', + 'application/pdf': 'page_white_acrobat.png', + 'application/postscript': 'page_white_vector.png', + 'application/rtf': 'page_white_word.png', + 'application/vnd.ms-excel': 'page_white_excel.png', + 'application/vnd.ms-powerpoint': 'page_white_powerpoint.png', + 'application/vnd.oasis.opendocument.presentation': 'page_white_powerpoint.png', + 'application/vnd.oasis.opendocument.spreadsheet': 'page_white_excel.png', + 'application/vnd.oasis.opendocument.text': 'page_white_word.png', + 'application/x-7z-compressed': 'box.png', + 'application/x-sh': 'application_xp_terminal.png', + 'application/x-font-ttf': 'font.png', + 'application/x-msaccess': 'page_white_database.png', + 'application/x-shockwave-flash': 'page_white_flash.png', + 'application/x-sql': 'page_white_database.png', + 'application/x-tar': 'box.png', + 'application/x-xz': 'box.png', + 'application/xml': 'page_white_code.png', + 'application/zip': 'box.png', + 'image/svg+xml': 'page_white_vector.png', + 'text/css': 'page_white_code.png', + 'text/html': 'page_white_code.png', + 'text/less': 'page_white_code.png', + + // other, extension-specific icons + '.accdb': 'page_white_database.png', + '.apk': 'box.png', + '.app': 'application_xp.png', + '.as': 'page_white_actionscript.png', + '.asp': 'page_white_code.png', + '.aspx': 'page_white_code.png', + '.bat': 'application_xp_terminal.png', + '.bz2': 'box.png', + '.c': 'page_white_c.png', + '.cab': 'box.png', + '.cfm': 'page_white_coldfusion.png', + '.clj': 'page_white_code.png', + '.cc': 'page_white_cplusplus.png', + '.cgi': 'application_xp_terminal.png', + '.cpp': 'page_white_cplusplus.png', + '.cs': 'page_white_csharp.png', + '.db': 'page_white_database.png', + '.dbf': 'page_white_database.png', + '.deb': 'box.png', + '.dll': 'page_white_gear.png', + '.dmg': 'drive.png', + '.docx': 'page_white_word.png', + '.erb': 'page_white_ruby.png', + '.exe': 'application_xp.png', + '.fnt': 'font.png', + '.gam': 'controller.png', + '.gz': 'box.png', + '.h': 'page_white_h.png', + '.ini': 'page_white_gear.png', + '.iso': 'cd.png', + '.jar': 'box.png', + '.java': 'page_white_cup.png', + '.jsp': 'page_white_cup.png', + '.lua': 'page_white_code.png', + '.lz': 'box.png', + '.lzma': 'box.png', + '.m': 'page_white_code.png', + '.map': 'map.png', + '.msi': 'box.png', + '.mv4': 'film.png', + '.otf': 'font.png', + '.pdb': 'page_white_database.png', + '.php': 'page_white_php.png', + '.pl': 'page_white_code.png', + '.pkg': 'box.png', + '.pptx': 'page_white_powerpoint.png', + '.psd': 'page_white_picture.png', + '.py': 'page_white_code.png', + '.rar': 'box.png', + '.rb': 'page_white_ruby.png', + '.rm': 'film.png', + '.rom': 'controller.png', + '.rpm': 'box.png', + '.sass': 'page_white_code.png', + '.sav': 'controller.png', + '.scss': 'page_white_code.png', + '.srt': 'page_white_text.png', + '.tbz2': 'box.png', + '.tgz': 'box.png', + '.tlz': 'box.png', + '.vb': 'page_white_code.png', + '.vbs': 'page_white_code.png', + '.xcf': 'page_white_picture.png', + '.xlsx': 'page_white_excel.png', + '.yaws': 'page_white_code.png' +}; diff --git a/express-server/node_modules/serve-index/package.json b/express-server/node_modules/serve-index/package.json new file mode 100644 index 00000000..cc50b13c --- /dev/null +++ b/express-server/node_modules/serve-index/package.json @@ -0,0 +1,99 @@ +{ + "_args": [ + [ + "serve-index@^1.9.1", + "/nodeapps/https-test/greenlock-express.js" + ] + ], + "_from": "serve-index@>=1.9.1 <2.0.0", + "_id": "serve-index@1.9.1", + "_inCache": true, + "_installable": true, + "_location": "/serve-index", + "_nodeVersion": "6.11.1", + "_npmOperationalInternal": { + "host": "s3://npm-registry-packages", + "tmp": "tmp/serve-index-1.9.1.tgz_1506659829376_0.796724762301892" + }, + "_npmUser": { + "email": "doug@somethingdoug.com", + "name": "dougwilson" + }, + "_npmVersion": "3.10.10", + "_phantomChildren": {}, + "_requested": { + "name": "serve-index", + "raw": "serve-index@^1.9.1", + "rawSpec": "^1.9.1", + "scope": null, + "spec": ">=1.9.1 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "#DEV:/" + ], + "_resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "_shasum": "d3768d69b1e7d82e5ce050fff5b453bea12a9239", + "_shrinkwrap": null, + "_spec": "serve-index@^1.9.1", + "_where": "/nodeapps/https-test/greenlock-express.js", + "author": { + "email": "doug@somethingdoug.com", + "name": "Douglas Christopher Wilson" + }, + "bugs": { + "url": "https://github.com/expressjs/serve-index/issues" + }, + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "description": "Serve directory listings", + "devDependencies": { + "after": "0.8.2", + "istanbul": "0.4.5", + "mocha": "2.5.3", + "supertest": "1.1.0" + }, + "directories": {}, + "dist": { + "shasum": "d3768d69b1e7d82e5ce050fff5b453bea12a9239", + "tarball": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz" + }, + "engines": { + "node": ">= 0.8.0" + }, + "files": [ + "HISTORY.md", + "LICENSE", + "index.js", + "public/" + ], + "gitHead": "a399faa1801f02ee1885e5664ed21a9c7990b63a", + "homepage": "https://github.com/expressjs/serve-index#readme", + "license": "MIT", + "maintainers": [ + { + "name": "dougwilson", + "email": "doug@somethingdoug.com" + } + ], + "name": "serve-index", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/expressjs/serve-index.git" + }, + "scripts": { + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/" + }, + "version": "1.9.1" +} diff --git a/express-server/node_modules/serve-index/public/directory.html b/express-server/node_modules/serve-index/public/directory.html new file mode 100644 index 00000000..6f7e7b61 --- /dev/null +++ b/express-server/node_modules/serve-index/public/directory.html @@ -0,0 +1,82 @@ + + + + + + listing directory {directory} + + + + + +
+

~{linked-path}

+ {files} +
+ + \ No newline at end of file diff --git a/express-server/node_modules/serve-index/public/icons/application_xp.png b/express-server/node_modules/serve-index/public/icons/application_xp.png new file mode 100644 index 0000000000000000000000000000000000000000..d22860a3166820b8fdad71c6505a40580af14b2f GIT binary patch literal 426 zcmV;b0agBqP)wtp^MwsrC67-bFzu!t;6Q^%|k2MJ$kfh*aj@vhNOIJ zWFxBVQIH79u!vw98!Ll~y$OKnm}QK5wtxPNU<+B6{mDR{T_7M%l&baHE>bEbHX04+ zn+OzZ0e^b{APT{9E#RmJ5)l*`)B%#z1i)YIM#v1#3=Jvuyn6YS$$CoGDq?9U@APAh~ZOF>jp#TVKsZ^rDVDQJO z=z(unDix`Pp@6(DbUGbswOaq~fE^0}P{J^D(r7fOTCGyOUUzmBMUy*UwAN0eHX3ch z0VGKh>h*fm?RK3*p0=MB(nc}0O&K6sv)ObGuro)jd=1C!>krB`s44?r3Yg)uiG7!8OBL$a-Fo@&0(0LjNH2#KGJZi@q2YVKu xMc5!EfO4vTMwnf`nA&W_@!!aPwbiWO`5Vn?>V~$MffN7$002ovPDHLkV1l0g-PQmA literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/box.png b/express-server/node_modules/serve-index/public/icons/box.png new file mode 100644 index 0000000000000000000000000000000000000000..8443c23eb944cf8ef49c9d13cd496502f46f1885 GIT binary patch literal 555 zcmV+`0@VG9P)i3lOYrtSl@<#7b-w zf}j{s!5HvocfT|9z82@(O@vrwU^wRt=bd>tXQpGD!`Kvuv@XEI8~tgUP2L`{+*)U@I@ zrVtr5X14??iAF(=0+k>q)v`Scm$9&=i`*knBsnaUVL1>ti*O1xfzmiD$%Md-h*6M( z@*iB)icu3eU424Ok{kp%Y!1dvp%f0`ac9vcupx^$vU0xuKpJcBvej0UYk%)EV>mIx2hV}QRf#LX^Uh(%`7hZ~|KEf#uQ31s002ovPDHLkV1hgQ{`mj^ literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/cd.png b/express-server/node_modules/serve-index/public/icons/cd.png new file mode 100644 index 0000000000000000000000000000000000000000..ef4322357cbc34e0b5eeed34f9fdf553a1de2ee7 GIT binary patch literal 673 zcmV;S0$%-zP)fk+XBT$+GFLor|=G~7Z=&Bd_^zJLLP z{dbOmhNM(Q`mp7h`OloWYysF>=iU40Tf#?V356IC6~fPKul?5pw+W80zw#nVEgemD zincj})E^?AZGqXAKHDz@mch}3iwfqB3rPo#(gwa141DiTF(xO6U^eE%d{-hX0gf3o z8{W?(@4ZV6pRS)EXbxQZMi1!D!oC#YJOO&yAsn%9V=twmsxF*P_%ZxvD(XXc8T9DS zr0103x=g@fvEJ!1y5C7b$Hz+ryB7+I5>V>_sj5lWnV>%bWD?LRmBAb^h}fbg923Y3 zqK41OM-q_X|0W}n)p3}pGlwoCoNU0Ppf+VweFB8`9D=Abd!7lXx6+7Cma$90A4ue; zVKQTfc(bHa=}i!!qJ}b>M^UnvkNQWze=dVN?ZJ22Mf(14f#NRkt=PP(cyuKepkb#y3Gz>xmDvuMC zIuoRtGlX&@?9*%nGA0rvwq8W9jW)GLrXJl50KN-ci9ozQ$MNkH;k<IV|^+8goU4jB6C^%Mg5h>3Q7RCr>7r_DEKw7k44$|vUmJAm;${=2wBT`(Pek9N? z+*$Z3+nYyu(=ufrbdbTWW%|!LE6aD^rgi=em@XcV9q^{200000NkvXX Hu0mjf|3D;c literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/controller.png b/express-server/node_modules/serve-index/public/icons/controller.png new file mode 100644 index 0000000000000000000000000000000000000000..5cf76ed029a4468cfcd05c1a50089a98e718418f GIT binary patch literal 666 zcmV;L0%iS)P) zlg*1#VHC#iD%uAHty;DTg0}q?ty;8bDFzCDreJ80{BB+R< zJENR4PZMQi-K$n$6{M+e{`y zCzHvi{{^55g~BV5NOa+FIKC8%#WFEpk_S+;0uA4flMsu=wvk9g@eiQYYGoUZ#;;nf zwk?;-FdB`3VHmiWEa5y`gl|tCa~huHAQ%j?r0MVf0GiFFt=sK#C%yTk;Ec=V5(eW1 zy!^<*iw^+Bx5qH>dSE^ra{Kc6JlJfuBMv}5)@Yi~=Nw?K*=zV6|Ft zLOAX<8jU;B^k)=l4vT=l&3kn^9UxVL)9GYU)9I9}vfXZjQmOn(B@&4pQul^EU^1CN zHk*ZXIt^qGkTG9cEEbJkuV?WZo6QC!5(!Z8c%13?`&?OQ#B#^uF;uHnNTpKPc_2n0 zqyCI{R;g4puH&IXp%AEOGKB zFaZe_Htgq(0OW7HPl9o7Hk+@=e6O@xZTY%@-!Rz$1Rlkwh5!Hn07*qoM6N<$f($t; AN&o-= literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/drive.png b/express-server/node_modules/serve-index/public/icons/drive.png new file mode 100644 index 0000000000000000000000000000000000000000..37b7c9b27d39acaaecf06951b024ac08afbfd4d2 GIT binary patch literal 346 zcmV-g0j2(lP)`6pHR4C7- zkv&QTK@f$%UVGNSAB4p~7X&kJu`rW(3s2w)1kd9QoMeZ&fx$)tn+OJimk zjCT$JD?{UrQ?3~v=-g&C?-zWP;E3TkpyGrhTDFaQSzpwKU?tq9Uh&CO=Y?-R7%>t` z!bl_(!*h(_r3OLS;FuM!k+?!xBDEihL=?r53TBrP2>202N!*Y~*dL6MvS5Ku!P&n9 sT@vv>?encL=G!4ixo5^&>-PTUFAyGx1U4B=kpKVy07*qoM6N<$g0$g{=l}o! literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/film.png b/express-server/node_modules/serve-index/public/icons/film.png new file mode 100644 index 0000000000000000000000000000000000000000..b0ce7bb198a3b268bd634d2b26e9b710f3797d37 GIT binary patch literal 653 zcmV;80&@L{P)WO3(`_cf+b25@DJ#zdQm}8GzWtq2-QnZ8W6mB^kfeK5f%S{ zUW%tGMCwrwic~ZrQcG=4f?5bkV+3dRk8hw6bk~y$KX#b!y*J4EJ~>;dRASqrSu;ZpM>?P}K~6AT zWv6Dmq?v&9LdXC(m%WCO6ma_di$R(v$@ad_>@R41N3N5lSJq9@6CGhX84-$%Xrd_6 z;){?{E|Ytt5$S-&Au>t4wDlIxdkfe-a22LMj``McG};r8@{GsRPm*+8fFey6C)@ifDBXVyTw(N@Xd41b45OFg6x_QA zpwLiigyy~cVoPxW^r~C7ZQpr%>1$*HKmv~AY-qJw4;gUecS--wnqslISSS=^KA&Ic n@BK|Onfz#3R%n{$a)0j^sqv5F(1NTL00000NkvXXu0mjf3S}fX literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/folder.png b/express-server/node_modules/serve-index/public/icons/folder.png new file mode 100644 index 0000000000000000000000000000000000000000..698f3d303687ec4157b411e663408d6c78944269 GIT binary patch literal 634 zcmV-=0)_pFP)ph+MhN1^33zoMD^Qf+OIbI z_vzZRHrl2)_1={G_UPKGHvRhX{`~jauQl4MHQJ#z@6?p>&M@@WPy6!9|NZ*z&vNe1 zcIC=+{`~Ov-**4~_}ZE_{`~gl&3W(8didmy*|aqN{{8galk(9!_1RtU%O?2h!v6g6 z@6v$ShAi&Ri1pr);lf_`?X&*+@B8=a>A`dH&}{P1Iqk}7_~w-M;jG)XJpcav^w(GX_Sp8| zeD>+d|NQmh!(aL7q50{g`taQP?5y|Wi}BKO^V3K9=$!J?dHCj)_~nuG-KX{2W%k~7 z_u_^3;eqtqp7hsL^3;F!-g5KWmi5|W^Vp8_*M|Q4?%I?!*^V>*{PNg`E&luOc;lI#g?V|#d$J3Kmj3P0WE89Ckq2LIayw2pn#a5gpo&Z zVQHa4ab7tqP=LQ&$tt8Y(8pAfn~9ADC?Kw4<`Nkj738QR#l^@06i_yI4UbPrP71Km zmgHmy3go+mC8TC%r^k5N=}PAV1qvb()3S1MGvcB>ZS@L34yh=rfP$h5Ln6Ee02${e U&JJnEtpET307*qoM6N<$g314QZvX%Q literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/font.png b/express-server/node_modules/serve-index/public/icons/font.png new file mode 100644 index 0000000000000000000000000000000000000000..b7960db9dae7d1da77ef3acc46d0a6a9da584267 GIT binary patch literal 567 zcmV-70?7S|P)(R5;6H z`2YVu10|S&W(GL4-*9m5zR~L0cWa7s=goeHmKzfsTW-vJJns=rXO>fi=YdvYp=OyIuL^83ysEIf(LtP34vHf@P1syLa4L>s)tjLDRY?|E+S*&m<}gEDA3wCC|S1 zC~n%F`=*)aLx8xUX62**Ryh}!5;VXx>jJY=!}V2J^Y4E*NjsaSAA6F^IPpwJ<+6wW zU8=5LQujKb`Z+F#fckUgU8t^YpU|s(=Orx83-p>b9R3rvXOE zXGG&B-+ooO{Lz1}<{Ou-vd(X^%s98zwd(4P#ubnMhqc}OsqDB<8mj>Yv8NgBOD@j_ z`PDq_3`$^`C!g6^zTp1k={a?|3Z-|`5HYOAUEHcimi|xPlFJZ#%{{hX{-)aXO=~Z^xE1+b* zM@!rH@FJ(e3$Fs}uKo9|x%%HQ^w?fm%Wa0V&kJ-j001RVucl)dd}jav002ovPDHLk FV1mw881w)D literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/image.png b/express-server/node_modules/serve-index/public/icons/image.png new file mode 100644 index 0000000000000000000000000000000000000000..fc3c393caa3bc4371d12d0c67ffd6d333ecf1d8e GIT binary patch literal 516 zcmV+f0{i`mP)0oSgT$J*kO*Aq9I~CW*s{G*(t$KS{OS+#aO%?udUme<*TTEO`Fr@r_QT zk=#}u-n~>Vm!+9S1PE{@3<)G~CPb<$Za;W?3+O}|+q)?*Pn355=}S(XIZmEANjZci zf5 zj<%@MX^bD1^BwlS^+AD|$dm-1wial0hwPI;CDM?Y9SXW#@w-UF0SQ8OgplRTleOB2 zUjkDS|0U9pI|lSN*EvXUa~*UIclJdZ#)Npbwh9>YT?Z;=B8|l&^t~P~om?<5Lre$+ z;%`P>SL7`djY#8Y9$wv9dv|3p)mbpQb1@7I~O+ue5CWtZi#AZox@gcwb{Xkx^Rf;Ty8yn6DWhJV4kC*wg94<7Vt zlteKm5+jKLV^qM1yt2HO4YZw^&a^Wfzb_m+@y40e_0^+M6ajz$03Zl}fU=sqfA9W} z@#^~O(a%3QB{YI^J_A4y)M^1_vjjn1H`Mc5t@6>y50A!C6seTL>`UqQ7p$DgY@K|> zQm^as;HM{#Qwj<3}(>R-AM4&+cd0t49%y2X`UaCBJg8YmB)K#uA{Z>9n zOp8>WCg#&r06`o8oz6gaIn`fY2FR)ssCr@3rc|5f%`bIJO$zbt__PK3gH51Sff`H}0ZWac9&q~*( zO@qNscV0VSU%X#sYO9)Qx4M=(eR(m}UFhondELHSnO2hr&mMO3 zv6gmw!P2y#u0c!?LPO88NyxOTj>XWm>*77F&55fo9Z?)iynObdfA;SdwVRl$W~G3* zEGt!2+1T-%ja32&!XdoMS_mM#IQK#{6D_nvjYu`GlvO3XdE)qYJJ;70)+jEP);68^d)m`eN0o>(5%D`Q(1;j>g@G;xlf`0VBQ`PFY?6)!N&f?*K}$p; zB!U=NBn{eB8${1}&-2_L*HuZp@ZP1@clS@cHp)4iM1ewzw59vko7eMM{e9z|%NNdX z0V;`?KKSzTCvTm5bc{L^CIKLUxc2X{i{ISz$8Sgf{q)1nXTP{`{s?9mQ$4&hPiKC- zY8q7(Y1Xu5iCf33=O4Vy(+|zQ?rW#gkKB0f%}?+6{G*qT22|DQB-73`YzA{N4W^=s zq0kQYcbtFfz zLz)H<&|z(Y4kBG67=JY6c|L1R-#TR>fC$3^Y%QEnYO1xHsf)+GU`3F<{J0kR(;pbF3)zyg$H+idfnl-wl5Wkh!vUH z4Z32YP=l_}1rZd1W_D&^$A($A+&a0e&P?xx0!ctY2}*<#p+qPVN*B(YzvAWXa*%bzq z7Fz41LKILT(GWohi9|LgIzSZBhb*Zf6R6O}WYQ4GOi&71s9lmll0x6;8&ILOl$j(c z0Z1T(6Tg09{?wd{moFHNN6PS?$|e>1MxSJ(0Z7o2)J-Zv|>acY@f`(Y@g7GwsEj5NLQo+q|HsxQ5}XSX_d@*^A9ZT9=A{W~j+$GyI1 zc4oqTHx@1FlRjw4XWyPN5i2~l_F3@aBk!0yu^aoRDvXy}8@HCjUVQUsuSH4$T5|r< zzZOn^?Wfa6y|Q($Hx4{ws+)wX6-HP4zo!S?4KJ@7PG@G3G{CjXs(p*kIrj6rHs7_y z+=<-=Q62s9FuWa^X~WKgJIAAZJR&XBB002ovPDHLkV1jCMPILeO literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_attach.png b/express-server/node_modules/serve-index/public/icons/page_attach.png new file mode 100644 index 0000000000000000000000000000000000000000..89ee2da0753040d1ba0a3487473a715a8fe89322 GIT binary patch literal 794 zcmV+#1LgdQP)i_t#ewV_0K6;=bl;e_Jt7$~$sQ)q$+ia<4Ec+jeaGt9oWH@O|2`W6&O0t!k{B9sUvLWxkCaPsd9W(`fa z;j-|^ZI^2XnzhgZWYRW-kP&J>DWPo`%;JaBX}or79k=+Jo@h%4Eo72tqev+cB?PjP zO<|ByL#>Tehyq$jR74O$B9WDW1`tK`LzYyL3A9iAcRxLkJ`I)n}v%Od-3H>j$OTBtk>(k-9o?8PqI=0 zB&f-+KOXVnjyKJlf4iHOtnuiE_4+ZVJ$dHjU<^o^YCjQ-wt^!;rPpBv(@pFO{9rdw98 z_s@3+yta93oyfL>7AD5}r=|`zS3Gm$_|(iSl8XBd9k%=91J0j2=ivT5cJ18ZmDjh{ z$-RMd{jQ#X79#Sc literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_code.png b/express-server/node_modules/serve-index/public/icons/page_code.png new file mode 100644 index 0000000000000000000000000000000000000000..f7ea90419d950f9e69d977a1f5847456d96a5f0b GIT binary patch literal 818 zcmV-21I_%2P)@LCln44|RX7Ti z0HI3&7jPq){odH{?_{%nYVq_;n_c4WbUpvU(&Cvnj!vq|kVC-vpF6vp^;;e0mm6HW z+WPzA`AZ|;pPp$&dNjzrc??4rt`k%Q1l*u-BPD0MQ}Fbm8jnsyezNt7+u{23>t7Em zJtETY?ja9KrVs^!LJ$xEMF3-bAZO;-IQJavE60KA7fO$VY_%N)R6s>g5mW>fL4&aR z*EVgKKTBXm!=L?S0?xM zYqL@C$|EDF2q*3zWW7;PDZ}SK*IE8;i!3U62=qn80C&*I1Le7WwNP5EcX;_oh2dJn zf#HgBe4@r$GcjHjmj2vAfT%(YN?}kK=(*+1*DkNNc1H5R++vfBMhACi<5uFUU+N4+ z<&U*CPmWi}REa7C6-t>2im1CWv5Jkefxa6>)dEj-CAW wWa{_}BJ!}~75?MkfaCnj>Dn=~vkLS70Pk`;z)@TQj{pDw07*qoM6N<$f@imYHUIzs literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_copy.png b/express-server/node_modules/serve-index/public/icons/page_copy.png new file mode 100644 index 0000000000000000000000000000000000000000..195dc6d6c365d298e466026b37c1959d96119ea7 GIT binary patch literal 663 zcmV;I0%-k-P)^@R5;6Z z(>-WZK@^7J_sq=QY_e{46@P+~LNG}sRzZsxQHvCsN*h5ir6^j7pq-$xu$N#V1gx}9 zClV7;5)7zih-s3DB)G=7|99>ji@So7-P24n=VQ(@GctDX!^_@$bj%oviY6e4Dh;od zooe%Wvs8LEKQ&&bL&@bwi=STIAI@!-gB2jC5+?y?VR~VkrNxam-`6*8&po|RZ5LpS zNKdJ%c4bTX`XjKsnecf%W>1%6WT?pKNdLLq{=(f(Col?P1+oq@R>)W(n=x!|*BIIh z6DJGw_w`)u6yN|vAhMteYK5#b%r5^v+VCFl1IGssaclZZMS{vs-LJ2$)n7DAr6==K z<29#%AXsBsDoO}SBaXR#_Ap!JKx)(1)3O2pj0_dYWz5By*X74fRT01$Fk%P_RzOMDtV?GU{nsYq#K8iy zb6qzLYDj`_f5$BwC*WE(t0m#xYJ*=jC2|HQYHh=pf#QG7oowi`h!L!{DB$8|qY{~X zu8@sU1tWq;n$XThR0%;45mdqXM892|{CJ@0DS*}>?ami06Q_^tvM~Y3K(_-`#m!8f z8f!QIrH4y#61;0Ym0cCoLl8{IPombPHtnn7%SbTdI&G-d>ZQo!_wBMF9nzX!g8HVY xYTJPGciz9XMh3w2fmZ(7v{)r*QZD48?mrio{~IaoqP z|1Ep}yDQG09bP~E^Dk?@JiKQJ z6-pO(3~IOP)IYisL6D6;oAEd;E%zR}{U$rMRNuD6nQV7nesKS>)yLo7JuDCrD>Abi zbj3uW23?^GA}9jQ{M^8v?ejL?HaT7AX5WPZNkBmfN`w-jL?{tT7ykZt$%Yln?p_m~ z-?>&d(LD(jAd}h=LPltPQbO$*Wbyl@G-_k5jXbb#qffHY03>M1jfEqoPJQ6Mr=Byp=^jfzePZV1 zLjCmNi31hdIJHa%e;5g=1(`u3BRzfeExY%=VCu{loOr{`%2hUR*x>tL^W_TTaj);0 zpPR6CUD1+0>4TQ6zVfH3TQ;%l6#(_%yspK@3gcmG#Q4!WCPyLU93nMKk7E2pcA=l45({2jNho>sdF*A~bA zxX?-cp~y_z_kFf+yqu3m#QiB}03?Z&9vvR5TNgj<)($Vm)xq5G>|o2sFMag&6aNF+ WAT1?sQBYt20000iHtsh1EzPArg^Q zIZrOk#rNsfjaSbMAL;<4h;Z=jvu8dzyz8N&Nb7=z03ZUw?9z%8KQEa6yM5=kUnka& z3?FJk2}L7q>na=T#;<7U*P91xfF`;`6%pVgWgRy0?1ZryL@%z52=-!fGXWGEn4M351L4<+7eDgwo|moqXT+s1&Kmn>-uQQ8mL7XY)w5Zk*(g+<3Y3tmkR!bL zOUKaUtj_pX26sH+=Iorwu}MGd`_%O-_sS}8VpG#fJA)Fcs#ezwtZf?q?Ac70mDv`rVs{$od?VPKeqf<-kUjNtS6ecB*mq<&M97K^6IVsDO zt2$Ru!b+>2S<}_H>$RcInusU_8PMNdf(W{sNlJ3FkrwMJPeBPO#d}Y^a{9TH(#{Y) l0D?dWAV4eUJX#h`!2gmISk&ZKd4B)^002ovPDHLkV1g&sd|Lnj literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_error.png b/express-server/node_modules/serve-index/public/icons/page_error.png new file mode 100644 index 0000000000000000000000000000000000000000..f07f449a44ff2761bfc7b752db3d08d0e1238b02 GIT binary patch literal 793 zcmV+!1LpjRP)lHwhvrAu0-@MQwt}+5~MQTtu}C0%;W( z1<{R?aHBz*g;pk%AyQVBR_Zu5m~;ES_vxI-O!vIF|H*|T{l`n#garr?$RMk>)?Y48 z(ZF2yTneKb};DNWF+jK)IF`6_IfJ{i|F3o%Q+l&4_HGBD|ACE8na_6>L z=s{^>-C(a7J$6=8A_%h5W!1K6dcL!D?XX+Ndk)oei?UundDpX_E&1Y&`)3P8#Ny0s z2Ag7_&ZPhyGj%)g&S6V2LNun1;iBQm#Fwlfv zgyESZR$X}2P;=RW!2zid1r$hBL{K7>2qi*f7>pT1=RdT3@-anEoH{ z={KFOO;Dh#bV*jaN>}M>RZqQd`S=6O9C3KpI~I>l%QFYfo;jqQYe5fcn`)+)zMm6P z4X&L(>gnN0!%J4^rhX->?$S5bY<=GEU%jc!KLL8sww-Eg;h z`H-yBHa)yfojYT}&G*GFc$<(Yja_q=lZvj66DC^O5%$B)|Z(CeD=n`|eM04SP; z>-=-l+xdJjA~vR6^xB#o{ehf~tSM`iwaQv$O<8NIHA}W_WOw*~ XD^gE}t;YAo00000NkvXXu0mjfl6ZQ> literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_excel.png b/express-server/node_modules/serve-index/public/icons/page_excel.png new file mode 100644 index 0000000000000000000000000000000000000000..eb6158eb5ca9c4b64c81e70e0fd894dbc8e2bed9 GIT binary patch literal 817 zcmV-11J3-3P)hdKqhFO_H1|Vn1E?(=|cjAh_&P}y{{^`u< zcYD@PK?$)4i~7o9*6F_$F$4lR(d4AAvrez^(88Hk+)+B7E)M3jc=Ewl4$S^`_qwSF zA%qz@=c2EOsz@0qB1IqsqJU)HaG&+}%`-OM8YqW{K85hqj@4&V9vz!Cm_n0-W#f;# zeEpJde%vdgRn5?(+PY=W*z~|lT2-mtown({ll8&3S5+lWz5K}LTRW{k{eJn3Qz!SU zQ`@qI_n2;K?RG~pYJ9=dj-RWgG;P&wEuoAxL~Q)<>x0b=dED^Outj&xQ^rA;u3pw| zca_ClTh_d9cxXg_U!lLRl0`xU@$=UXO|_dRdtXfKwPawmnf(LC7u}-U>8k6}3u|{8 zs9LHr>MIJZGD^r9h|q2yF24Wuh+PM^yMN9GP1$khlDkdyCY}D{kg}jEf-(kW5jBY> z0rB29ZhG-r=i_R{;+1k0?A-sBM;AP6(k1i9ZuixR4?MqXOvphQgCYj~RnXKKL~J9Q zIDNz~XMfO{ZhUg&BTtMyXJqDVqc<x643?SvKHx004lTvR=0a5$dUw z>Xb470000$S;ka1sfH4I-R8njUol7M4dtApOahDylptpYswf1hD#CwFoz6oEA>(SIECU&IQ%a}GXdnC!9$70`0uH1B00000NkvXXu0mjf!8w72 literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_find.png b/express-server/node_modules/serve-index/public/icons/page_find.png new file mode 100644 index 0000000000000000000000000000000000000000..2f193889f7ea091c292acdd684c595dcb206b5c4 GIT binary patch literal 879 zcmV-#1CacQP)@+1&aazfGU7ezSm^v zpACwO+tu0su66!(dT=`e05DeeCnCFJW(8|RKtKa{4LGONnx2V85A4m%PEQ?MEtR-esdM$pB-`H542D0)N2zSC6Imf)4L8?>%ZrW+H>xCKi$unm zvGZq-*Q%Aahx;C*=l+K%-?>XB)6TB$-L$r*`RUvlA`xP1NG2?)ge8@TQ4EN|Jks0u zcDg;oFC#-#R`YbWB`D?Q`1#y7l$LXhjSLf8AvQuB84}i#j0^!#g{VE#(K7h@5pFHy zSenl=@XBEdxp`h2Ji>CR%=qXJ7!e|?paKet-~;#ok#jETyeB(5&Bkhp;!+;51~G=) zH?L7xmDUu_h+a$+xuWom;AWW!mS$%%+436Rjc@}y?l1134kgD0AOf$OmjOR zstUlshZk$ZC!bAyIg{Y29z#&@3SJ;6D4+_eFume9^#TmMccC5u0J!ZCTnO6m$lnD| z5JeFHf`Xs~1vP>RLKI1GKDY<~pjr2&bi(fX;6Nj-ss@Ds0CcoO0H{JsEQkm{q03skAA);_bv3q{k31qwVo&s-q`Z?_e+j^w(WL? zl+uETs5+~xBU2};OqEE9ETLGwsMGe1%iTRNue)9}|0~E4B*@5#oRXZ9oRXZ9TqRep zPrGZuoOON4n@=uPbyP1y4G=+HktC6l(gZoFD>@_lXDrN?wo+zozGt3P=Qh+3L7+}q z2!WK7geXLnO3Vw;o12Skp%_E#+N#9;DDWP?Q-VS3B$v~Ha)dDzWn0zG~O(^_1!n0HYp-( z+;wPIdoFgQlpYV!10V>5@a)1LyGBMvoa}miyp(bxbMTM-FYNyx;V@TfYddyT00000 LNkvXXu0mjf90!wr literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_go.png b/express-server/node_modules/serve-index/public/icons/page_go.png new file mode 100644 index 0000000000000000000000000000000000000000..80fe1ed0cc75fbb67e9398ae686641f8fb287238 GIT binary patch literal 779 zcmV+m1N8ifP)JNR2Ufr z!Apo%Wf%b9=l#x^8AolrB&K9H?Pg_|78WA8(M3toqE%3B#7*srcF`i*xhupr27%Nr ziguah1+mN)U5GNmyEfQ3-e%_i&-vb-Co#(>FJ+EhQEwjRYVQ(&UYy{U@%vbY||>@4x=B^vIqabI?L* z;-S&DS^V3-ni4^fl|HMkOEbgX)(390>A}|VIypb5Xee4g;7ck zwKh^A3Mi1Mh@eC$5lV!}Fw%sP623U`g3pd_Hr5sunLvTskx4}&Gm%Q6L}(l4x}jCe z*81q1_4-O*ffi~_nMslo?EQ8t*&Ec(pzEw$vc}pKn_Qp0>D7Jr>ATNC3w@9f|Y+U&+)#!t7l&wKp+nP{PQsb+fb=Yf!Fu&5j8vpRj{FT>jD z>d>$sx;A&+`n$HcF}&sYKSyR;=(=9tvvOj@hUG;~4qTYk^_@E=?$*^_pVh_bGnOt~ z;pEw)j{SK$XVc;qy181rT655gW9NG{(yeablViIL>cDI_ux8m>Pp{tY$J0lgo4#ax za?j0EA3s0S!f>{~ykN9h_RhM&g3K(E`q(dE(Rd49+%xMeR9{qlWnmd{s#(SQ>PmFtSQqUjAtB;_Vvt6}AS_5YgM`Uqu`yva+H8^=4U$e4gHb}u zAQ2N{V3A%pO|?Pv?tb6z=jC}SiRa$G^v3q?*6XcYz$p|cq{uLj@#~Fi`J(>5{@&&N zy%T^+;>8cXx%|o77anP?&W1?1A(>-T49z9pyeCl@7YI+Si zKti7=B~``}TImz(G{0PnlQA3P#MAd}sorMjkP!50B7$nAkU^%#nl{Q9lW0@}9fE-> zN(q7tRuiC_T1r|BBtVBTlQ2+70$Rf;eF`Z;lx46Cpu-rEgb)EBKq(b^W8l<^We(`D z43?0=01z<3G6+UUv6`CsWCk6^93!#+<;ws7007{zS3k2k9-zZKFO~(k`>s0y006+1 zgF_jyIhsL-`FMf~JL~C=cV75(CrJ|q;MVO961G=O zm9d)YpJg5g(4i_HKL75eSE}mq$Y}r}hyVdcV~p>6a}oXr80q`oj%+s700000NkvXX Hu0mjfPs|!l literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_key.png b/express-server/node_modules/serve-index/public/icons/page_key.png new file mode 100644 index 0000000000000000000000000000000000000000..d6626cb09eb11a298b90a8a27b0d8eab41f49a82 GIT binary patch literal 801 zcmV++1K#|JP)$lC4gU2-`f*>nhR-;k6IP7e>YO!0^w)WK%3$w02v-#>5Ep64PCP| zJihT#O|N+nT7XR2h7dAB?UEAOhJF^mol1i`QtQB`HSY}RE7=r! z)zaVIHr5?>v2Gz&fdYw&2ug$!p+txby(aWZ7(4QT)l2`jX7eMQ{>)lG6ev(fWKxmH zOr%mM5$6B%u~qGtCf40#`mbGj3s!n+^%wnJ&#rl>g<4Z)lB5J6f!?|AP275)Zswr* z%T}4~{;_(?waU!#?JabbF3Cy-kf0{R{z}6$e=5yMQKt3BPcl2>zoTPMqMwF;3!_n|>sT?~bK_-2O_m+o>GJ6h zt=+g$4n7y%1qVJI7*5Yw(hqM=JusY{d}*?U(Oj*gT655eZ>Ksn(qrd7v3}DX1}C>` z+X+8@+4-pVq_fxG zlU}~Ye!0+%>J+pPk+0wV{GM$QaYM?5ux)w2z59=S&H2+K?;gH$bZGzL&g5>G ft+noNiyiPkP9r@8gT|RZ00000NkvXXu0mjfuqTIu literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_lightning.png b/express-server/node_modules/serve-index/public/icons/page_lightning.png new file mode 100644 index 0000000000000000000000000000000000000000..7e568703d6432c530224e443771a04fc1e2e59c6 GIT binary patch literal 839 zcmV-N1GxN&P)73{`^;G#xwAtHz%LU)4b zqTRU=ve1RNa3QT=ZM7C`iJ~QFQ*9t7<~pX$d^7W%^M8FFCkcQj-~0ZRTBCB(J0^iD z-~e!d9LR`f3#|=(>$bPvx_D-~2jC%pJ=n_e_OK zeJ_2b-KdDDh@@UlzBSMC;EPygH_MwjWBnPGQegihBV73D?-x9PlHL9A=(Vg=8^d<4 z<9r=UkxuIm)*CO=9e###7PztDxUv}e?$0)rQicmYhV`pQ%S!g@;K(?TVfhM#E?bM| z=B0gfb6h@a8bf5FVT-SV~6}?X}9lK@@Yynoty&1zdZP@?RfODsl=2XzzU% zS8gIN43How+9%bK2S@Xbc`O>`z5`%^;pXGy8^4f>9^3!Sp@|O&)m;dOa3q6d;4P-l zca|=H_{G&m?D_+&-}r{u-J$5T=(X4R&)q|O^gN8cgv;s#@5sEPT5_Z)oFo9Ac>l+I zc4ng5zHpps|9)<_Rw>5bKzE(M1j)dFWI_%OH$BJSz0?T+02W0)_a>#vFqb!*d|5wB zzBUN|M&ty51O@=i?kiDrjQ{{}e|^rU?OS|RdxxP1p5mAw36cX72#`R6UsoeCQFI~! z0ATITp!vfeYyQ?Dr=^5BAshfEa0nB~JG?nUa2Aur006MC*<9`)86SPS(W^`H2n+xi ztOWohsFfVfVWrI7PSKW}BmkyPoj(-|J?ES|BGd-}fIxr{00@ANnO*ZR`#)pee4I5T Rmm>fG002ovPDHLkV1i|Hc$okI literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_link.png b/express-server/node_modules/serve-index/public/icons/page_link.png new file mode 100644 index 0000000000000000000000000000000000000000..312eab0914ab59271384686255d1be913a6b3add GIT binary patch literal 830 zcmV-E1Ht@>P)VWgGzD=Y79#JI$lhEn`|2MpRa?Bt#-nSD~P0P(mbVe{KrOBoKnSsk>m|ML{6l zBosu@om4j#WzNLRAk+{k1JRvL(MfE&vvbb->v>W{*z*1_uMP}0cIRX*?mz+wk%*#O z%0D-+$B*g1nRkvI+_3E8Pr1NC6@5M&4vWaLCnNlr;lNlr4i91z&)eBGqL{L{GNu;Fof}GS9{gM5BJuH;2QWk8yuOZdB3pGR#s8bd~ zAmt<>3Q=YH$t5YJ5;7@+8Uh6=ktBgY6#6Pa%2F?h910?U8cLT43KAj$Z1*==ra&gILO{WkHfs(--F=bly9l~${z@AT>V$oat!YAD@M zBE0v_F{`g#^wOSP-u~!wvlmXdd*uqFqoZ0^{&nEMDU+=!>({S0wrQhFmoB}Yq1)~0 z^{A)L8Xjzdr(W4_exYO6u3a{4*kIeXZMJUR>Q=ksjW_p!rAwDKYUs90>6Q|C>56o@ zbrSq^Xk7Gq#>dAsn@un`Hz$?w$;Ss`%jV7L%9ShgHFV~C)6M>B`Tp%|nqPc&G*A3| z)Qe+}vT4-x^t1~XE@(6wR;^lPWMo9n*~E!cy~)YRsT2{`?fqeIw-e7N@mOA%UcCIq z_kH(_EK7|>pM*1Wt2^DaDAp|cvp*@(ZZDKpYkKC^?97(`0sb&XTXy7N#sB~S07*qo IM6N<$f;YmCWB>pF literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_paintbrush.png b/express-server/node_modules/serve-index/public/icons/page_paintbrush.png new file mode 100644 index 0000000000000000000000000000000000000000..246a2f0b426faa0c7f5ba009e32b1deaf88d1288 GIT binary patch literal 813 zcmV+|1JeA7P)otxGRZMDZ!_a~nK|b_-`n%VosaL{KDuPV10`(1LIen8kX2Xff$3BE zah#djvFGJ&eE^89Pk*-O^+&d>FC~^GjRYVQ(uuPJyS|-v?9lxA-+tM5>1Qu*n+Ir1 z6KhA>X4$XDH6?-|E5oe1E?pQ5-M;2xw_ex!x}I2+b=}mPFW$U%^;o(Zg*LP!K^1kP%8ynsD^= z1y^6xD1#GLjO{VLdh@0GKY7;d$+NGukV)GRLPn^=q=dF%B#XaJrNP`0E6=}e&Gj3d zKJbQre*WXt!60_DnIzgMQc6S#fvjXxsE1v7;T;njHkdy2miIqAS(nX~o%cO+q+b#h z5tIleLWvL=dQE8OC#{%y*Tnku&K`Tuub&_ELI0t_ea{@3f>Jv&sYqld(%}3_GY3Dm z;O{3*Y?v^A`a|D;^qrM=ykI)U6QHd%WhO~VF!SGjGn0GOZrc3mGZudNl9{Q#X5&-F zuGwVReFLBjE5jr!!^-5*L%!I%PkYH#Hs5rMrEBl^)9)9XTD;xjHFxVZMc3~Dw6#k$ z(-S}RE$bgMHv6Z`mS5|u$$78sp4G-8b@lVkl`HtEv+MGn!F&bKcHPi$$oP_;=BrPf z$(~b3&p3CsuQxhoV$%jIR;`lB-s7FDX)xCTXuJ7ZyIQk96uIR=HBt%-P?N*bp`)EF zq14c}QM+O70NTOa@V~_)&GMZ$^cQDlkyOCa(H3Mf+6xhCuZh`VSN{cQBl5Ys9{cp( rh`2H3A^=GuC6HjQ*7|*0>;m{7QlnX3z3MSD00000NkvXXu0mjfR5FYo literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_paste.png b/express-server/node_modules/serve-index/public/icons/page_paste.png new file mode 100644 index 0000000000000000000000000000000000000000..968f073fdddc1cc0f0800b1ac4001cd9a55f053d GIT binary patch literal 703 zcmV;w0zmzVP)AVs!l4K}n~L(tL`6d4Up4iSWnZ3Qg~4n+_J zDGk-qQdogO5JUtO-d5pRp7Nd7_r1^a|M&Zq%mn9Oe((|e0sw%Ur!K7T1pojj=U#f? zQM`qbQrM^DPkwa?DK_be^~z<~RgSMIa<`xP_4P7gg2jCwJ{9^k!fsU=#Ti|%I3p;>90Qd+7|~0h&mIklA#nb>ATL2+v$&u)OBgB z;nsHb)I&QRKeX40H~~cIZxCd}5C} z=79lXoXK%6YlyLtsV$~bSm?Upq|DJh#{|*a7XMm`4QJWZ>s6nL2R1|&J z0VPEwJ9?!n`o5PKAjc->P1Gi8BY*%!5&FVp=#)$mMJYul1Jton}gujiUf??eOy!x&!tsjxy;=Q3_DdcXx=a^OBhW0N~`A@4xB0a*%F? l+@c^sQA%W+?pa#c`9H5UNfS6T{e=Jk002ovPDHLkV1grvM=byV literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_red.png b/express-server/node_modules/serve-index/public/icons/page_red.png new file mode 100644 index 0000000000000000000000000000000000000000..0b18247da5850f3c2486373a3e179acd2772e8aa GIT binary patch literal 641 zcmV-{0)G98P);68^@7JE5sw#jpE*579S@TLkU(6yap1yN*Zuy>-hV%Q_v4Ar&!63c8OBr(ZRhFu z_kWs36-AmgZCT>x!RqM;Zu9tqvoHI~k@UmYo_g(*J3c%2{N8}7I+|qKPQzv}7t>%W zsu&9G)UmCzkDYSw{fBnuW4j;1fKV_nicw`$8C6D=F_qu`zUiK$2Oc?5UVY+D(`I@R zW`KlwqLftWHH3Z2_XVNfKn>VgT~k=@- z+N>c>0|@A_HbI9Jn`v0~7cfIF(TS69zaomDS1QtgvaBBfGEPLHccO2~3jc>n^6}^HAEh-2#VxC7YYcDXv!L9X= z-R*SOUvIs;n`8(LxP4~^2|JsiN^hq6cU}5dn4v1~Kl{eT7pm&f$PoY`hyVe%y8G*S bxB&kH@RuR86sIAS00000NkvXXu0mjfZBi!% literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_refresh.png b/express-server/node_modules/serve-index/public/icons/page_refresh.png new file mode 100644 index 0000000000000000000000000000000000000000..cf347c7d4685128a4a447abb9fb8e939417644f4 GIT binary patch literal 858 zcmV-g1Eu_lP)`6pHR2Ufr z!EI=jWf;Km|8+n2IrHqe<9xxFVk)&(Nh?w$Xk`TAyvb=#e=0aySC z00NkRDM597_LiNIJ2M^qhuTvB004REvvU8@of{r?P8tmo3;+Pk0F0@*jAMhdOkS&1 zhJPPfQa;pP0|4+Yk%#j>X}o-s#EF1_DMV93FsfPP`G*>Ks>L&)Q}w2g%slu0kBfW1 z+*$*0BC^oTl6>OGIq(9BgG4|C90Dk-N_mPazGrQ7uHZ|>BLD!-KmZ)z1e^#?1Sf(M z!6m}K(^b|i%$TcA5bC}r$tAA?0C)g1@CgWliJ;NAk&ZF+-w#}$`-3nZ32C6IVKrHp zr+(!L2hRfF&AsTw>_@ z1y23;E%Oz}?q^Q2d($ayO;-sON2t7$w(Z|o0Pw1YnSp^}0PI+I5HnDNsFCA?oorkG z5sUIGIq=FSyxcj+xlhkm0en=52Bx3@02o12gdAU$_i?v6iyFMuc7P9#zQ-Hf; zVuV$t9P5`m)F2w1?t6{<8%wk{w-PP#Sj#%1MbsjrSI6n;D_@8q9`~W98dNQf$j=iI z6~hpgww&be%X_HI50Hhx@W==u4TLPB;ei-J-1}G8wH}|{i#Lk-WZAyfv}k4y0|fvU zZTy^$u6L>2nWo(NDSV2@MRD}JQ4(c%G%=dG@_vxH?>gcH#*Ue2HC}9sapf8X?R$Z;XEnm&g zW99mh)5jNw008mK8)r^`_{yH0rNn%u1|SpC(tjf#om=+r#lh+?Kb>DVb9`|C0Bvbv zN3U(>f4-tAC1hosRoA7p(b(hL*V}(j>ug<`&U)|l$6o$)!>PBQ9RQSwn9asj2p*|xhU*R^vq?*Twb0t!lm5}`yW5lRy-U0ZYK?8to!;o!r!XeOE$ z0HB3T+6EEoI4PlR=wonwqJ+TvCoWh&$?CAPVYcU= zD{DS0?AkOtb@-hh^ZLq~FMjxYf19X?pa_YqtgZGvv2TaxcF#KT?O%=_*a-kW_;N|D zakkWsOe!)HsT5WRBiC+p;N-c>0Qwy(1D2MDBC595oXSiR07)sKNk-%9*rDBOO^HUD zZW#;)R&EZpqha<(HK$(tZYU#V29<@0qCXgU{gXeGpc_|pTqQD-WO|}%yKZbeX7k*H z2W~CK$v8NBAq~czrc5A(v51g0Wma7`G8}f=ZcuAiYYxZan@gP(;Ku66M6?bquGiHe z3Q0ya)%Lvk@kLixZfZyU@#UFbv+>pYhcj8TRKSr_sWG8i^X~UA**LvbD3(_Lba3xm ziYcpup*A9qJ$?AA=Og05lndxfwr`!C+O~h|B~4 z01q8H`StcY);%&mId7_+)76ovRpeNWRp&4M?#jx@|E-)x%P*A6t^fc407*qoM6N<$ Ef@ddc(f|Me literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white.png b/express-server/node_modules/serve-index/public/icons/page_white.png new file mode 100644 index 0000000000000000000000000000000000000000..8b8b1ca0000bc8fa8d0379926736029f8fabe364 GIT binary patch literal 294 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6SkfJR9T^zbpD<_bdI{u9mbgZg z1m~xflqVLYGB~E>C#5QQ<|d}62BjvZR2H60wE-&H;pyTSqH(@-Vl>|&1p(LP>kg~E zYiz5X^`c$+%8#zC{u)yfe-5 zmgid={Z3k(ERKCKrE7DF;=x4^O+ pzO8rLO8p|Ip=x)jHOtWj`bJBmKdh_V<`47(gQu&X%Q~loCIFbEay|e6 literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_acrobat.png b/express-server/node_modules/serve-index/public/icons/page_white_acrobat.png new file mode 100644 index 0000000000000000000000000000000000000000..8f8095e46fa4965700afe1f9d065d8a37b101676 GIT binary patch literal 591 zcmV-V0~O9lw>B8WRlD)Gm}Jrz31u-X&&gn2lvjs=i{7nIaL6v2==uw+8Lcs(8j27 z;|c`rmSv@Lx!heopGP^^Ieb3f=R!%Lpp$}iMS-&P3EJ)s48wrJ_Ni0~k|c47D2nj= z{jS6bt|kFpFf|p5cM`_&0Zh|`rfEp0(}=}lT#(6RpzAsUfxv^LSYX>WlAaN$>)*J5 z0#sE+JRUD8iT9*fz{)_^7@6P&!sEjTcD+I9Z4YjT1`wH@fV{cEvneYGFU%maIEU2s55&K(LixD|{p-uiS@?KNj zk-Go8G$hH6g002ovPDHLkV1hVj1#|!a literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_actionscript.png b/express-server/node_modules/serve-index/public/icons/page_white_actionscript.png new file mode 100644 index 0000000000000000000000000000000000000000..159b24075191fc259cfd80c797a1b0d74c168422 GIT binary patch literal 664 zcmV;J0%!e+P)7Z7t2}reCh0o`+ zAlt$F2tW%oO@m<=(B8a-_VgLl#~yUMUDWG!0qFPppd^03e+x1WpkO1NhIaKD2A)-@ z=Py8(Wi%R%JtYZG#sTKH@6Z+&!S3Edf8jFJJNKuva#KJQD3X^7;H^fd2di znEN&c58aUG>`>P{Vqq$kLb+TP{?I!d4(|o59X_%|nVEZq2Rk60n7072SWJ{64CV?3 zgS!EB=eYxwQ>P2&$}(iT6UMvuFgHHIEdNA29!EBtg=v~X!DxxEH~}L2zn|52%xalaq@DTdhh{EVwv0IaQ=!?daer zTKp4I`l8SDt;d{8Q`5Ko;BXUi&oAG1l4}59P-{|^S(Rmord5s6qsh<&m@Ab^wqCD) zHyRD}lKLDzpYN&@q5&*47mGzGiqcXpmqR9#K|CH8kXS4RNs`(iEF%HjP%f8ItyaZK z6$%Apvsok(2>~dTO5jTZfq;N?0ch4l01f$k9?4{~Youl-#x{UDMr#AFIkz@SDwPtQ z$gQ^$2|*(Ps9LQiav_8o8Ne<=Zx1*M*syo80sEO1tB%>5 zfdHB`1z+!R@?ghPRKmL)hWEvZE$=*54ose*0JiUNTM_)cMDXhxEKg(?-pD=y<)L4J zT0dSyD0&NhJ$^_8Ko9uom%-ZM4BTM{Tw$9qyPj=-9W;N(Wi@3*-Q4pq`Gcp}^vvNr zyd&PsmG>fpCSZz?K}UIEd;HGgG%0MG>ymxKPwy{>wy(m*Atq7)0000~7 zMNw2LQirBVQoa8G3P(rY+l;L4iy+JwSqmy$9JlSkk z&*$^Eg+c)@!R|v4gdc8+TTn&eWHO0VD&>$!B%o;;WLf4CNs=Inq9d`xA4otCWHK38 zmc{pkX`0Y=9g3oGK{}lVy~OYL|C5lQ&U^l;wrg|7w=BcA9L4-r411?K7f`@348&rw zXD#uW)DK;H`hxO}u%=@Cj{;#u#_;bb1_KgUOT2Hp6;)MvC6P$vQP3=g1O5#aU%I!K zZ1dc@f}YvG&*Spnplm2rIp^VdA^HydZ0X1axdms2!RKi5x-SFA4p@ zC@N|PI$ryHL@t-(!zBsf2-+sYAukhDHU7Lxm88-p zDk^c;sHj}OKUc4lGZU}6umlGVNAJx0%sKDOFwQx|V2pVvxhYKe|L9TNk!~md3BVrm zYPDL8Hk*yU-ER3~LGwJ7N`0ZV&nOhBI{~~A;@ND*=kxg?#^W&`4u`zk?Mg_e)8XlK z`T#M+OaR1!<#Nf_>$S`xrqd}OjYhoJ>q)?3vEX8pY&I()ERjfjrXM$k7e+-Qs3Ihj zNyOuEQ2EGYG7ro!o6VOBQEwuV2z)*tR8>WxP{616FY)p1Pn1d}#9}cxolZC$4n(6- z35hJq0;FlHC{ zp*iF(lgUK(E`($(s9pJ8Kn?(M734H_63WHtf}6SQQ_MXEP!#0|&@>J8dL5TfG&tBw z#tYn{TCGZvAr>cca%YYn^!t73tg8OOJ2FvJ(`YpCyVZi*?Ur+1uUA$hAg8-aK)c;e zQ<)!XwHh|n&ND=$@^)>aF-`~n}#*WMkD*M|f8r$i*z7+W! qF|A!t*4fE(R`<_YIkN&?Jng?3oQ|aAqClPi0000t>5xmo{nArfL4CJwMMm+N`pQ3p^Le$?rMud6Rbxz!-yG7bz2z$^USP5(;udf(gfQ zG~f68y^)EvcNWp#bUoDt2=h+^%o-?-|mo~iieWqLNP<0m@2PTB7ftyb= z@H`K$>v9Pr5X`L|rw&CEN2(9SB7A2SE;d|j9@*F}sd(@*2l|P*fWfK>1drZUrtUA7 zNXO~pKn1cjf~~TLbje1g>EPPzN2GH#UIBxJ{}S9=E`{zs-w#hO?vcH+hJxroI5v?j zD!4lP0WXq8zUx3RAP@|Gq$}6wXCjFLZY^YSWBxN9#&g)ro$%5}aYn#y=tJ_aIT%4d z5d4u`rlp!};XGmbZkJE*kYJoi&N0pd*yxY{0${xD;;Q1h^8f$<07*qoM6N<$f(}t7 Ae*gdg literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_code.png b/express-server/node_modules/serve-index/public/icons/page_white_code.png new file mode 100644 index 0000000000000000000000000000000000000000..0c76bd1297751b66230f74719504b2adb02b1615 GIT binary patch literal 603 zcmV-h0;K(kP)^~*-1fljz_B$LUvK}k?BNXe#Y!m=zM!!V#}8bncK5m;8VP zw86G*RI63?Cd%b9bX|ueNlZ|wR6rj|r_)VIP@r2imh3?SN+^{|kY%~8B{maJ@F*OK z&VH9LwOeGt#DRjj0~v~8`>iO7!Ybi;zE$va`A^T#yW`y44;k^#O~K5*jD=qcUhPSc zvyy~q;5H_1WT1l~cqje9yfa+l!hu6xjdOJ8s;8E^+=QQ$tw p?%p!Hy#YapB=@+^9(46X{{RQg%9y;OKjr`c002ovPDHLkV1g7l326WT literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_code_red.png b/express-server/node_modules/serve-index/public/icons/page_white_code_red.png new file mode 100644 index 0000000000000000000000000000000000000000..87a69145075afd8f8fd8b391c5da1249ec8b2889 GIT binary patch literal 587 zcmV-R0<`^!P)LWh{^|hy<@Q*xw+qo|KpY<+vaXbbW{L4q( zTsjXEJvb}e%bgb=o%W0h?4u1;^bWTqH8}5Th002ovPDHLkV1nrS0P+9; literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_coldfusion.png b/express-server/node_modules/serve-index/public/icons/page_white_coldfusion.png new file mode 100644 index 0000000000000000000000000000000000000000..c66011fb0fbdcbf210483d676b7131542a0e282b GIT binary patch literal 592 zcmV-W0k7R5;6x zlV4BMP#DI+Z{WQcKZBTk0lfkj5F$ztWhP#lcuyb@0@rA^#Kpu5KLA&Rgc}o#aSmis zrZC__xY^&#cI&!!{c|4Q_tcec*#b>|Y15wPcY2=o3;-Bl=(t4;6Ok*pL)-{*A;GX^ zS(@WGp6j~k1wBVR9)BB_gar`}HyRBXh7nM!)u5^>N~MyN6bc0-5{W?44iB<`2biXb zR;wk?jIQg@G!5l)SqhrXCU}x$GU-dY1sra}0uCq@153FUULT=jNwSk}0WBjKz}Jdu z<5gB*<^XtpAmp3m^ZEXQZWd1krhft}CoYaF4cSMvTJ01}X3X37KYdx-D0$c{doUe8 ztY{vlGr-e*;N!WAV%_hgUawyYrhegW>^F)pv%uUTFslHn; zvJ)l{%w(~{!O4`KTmK{Q{zCYltLfs&4?nz|6IdlqHCvX;|HGv~!QW?8P~_d#e0$v$ z)5XHEz{3>qMiH`1+qNYf?huS+@L`J9_$cjJF)Hf?@pu;)`9}BXwGUM{2!{y-4|Z{L zG>z?O%Cp8P5T#j1DID7u_*(Jg?7iss8AZQ+&;u_J{FmILf((9eoiL5nGUe>Fgq*U$z0000 zJ3A|*qoWOonz+4ZQ0KNhDB07SX1?#FrNy8%K)_l}y&kh`*KYdy`Y99&tgNgMLSSrc z?B?+B@HO@P-jS~z2Rgc6yy~Y~%>oJpBxsb$5<&nRLqiuR7K=@0SZj~jTs|sv_jWVX zGe?WflejOaq|Vec=s9+ahmXbyJ|T)Sl*?s82sr2H?Ce~HD5WI+Sz&tmWrN()wI2}+ zKqg92t*l^-#ae~;9%KFlWkmwnY=-UK`_|%ICZ#P1gdjK<2n38VXsuC7{WiU!fZFmm zW~Sda9(Qi@pxO}$ARY+;t##Ao27usOqNt7Hwq6K7G1il@xitj=LIM&{N&#SuX;x4x zmG6FhCg-$PI;hQ=;1iZ>F>^~@)IPi;l}fX?SZ!QiO=X<|pSVkNpJuLHzW(FT_~W-v z?vFpkyE>8ee4d=7wKauH5~dd_M7d2Aa=ICC{Nj7Blqv&DQEP#j_VeWV&WXL>c=LLK zsmYg^_JiDb;%U!UxO%qjFAvsDFj-kzT2$GbV(ZopPM$i$z`!7jvEk07BcC=6FMt4` z*0u3Sy`0b~%#(0000K literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_copy.png b/express-server/node_modules/serve-index/public/icons/page_white_copy.png new file mode 100644 index 0000000000000000000000000000000000000000..a9f31a278e17993d8d4e13beac2f9d5f7b42d08f GIT binary patch literal 309 zcmV-50m}Y~P)sF~CC`eaI+m%Y8jfzomMvZQaNUIT3LIrJ$h)_W{ zwF|LDNlB-g`Hb_G$;>3F$9JF3WYR|3fy2C+_wH}*xp!_4fF2UN4lt#d26oXwru}hT z0+0%Vz-l&|Tdh_L-Ng1G2*RBtBncRx;99K)&+}s0whhxXp{go}$g&Jk6k|vfypI5M z!1sNGVaV?!*L7i87Bo%cfO@?S`bajL{R<($@$|PtgBRcCGIJ_2a|&kO>G-s2aR3E4 zjssoScUa;zIdOeGHBnH13G)W-zt$kUQgNfG;96b=v&4NzRt&@7nN%v3HsG`<<+F$cumMs448N!W3r&2Z*b~D5^$^d6Jxn@SFK5Q8*uKSR7x{I|H-_N1f+AD zSYC5@2K4OKL$==F9U@CH;ONNL(W}oZICHn;d?~pw?GRIsH*x-68Oy6SuK`)`{E)46 z9^3(-HXa#X89SBv?u_YP)WjsQrp;}0X?Bxrvf12IKW8>3t`e~W9|JS<{btTNbNT@EQIWBSNJTX8AMGXD z-SsH|s#>j9Xf~VMtyT-YMD}5^SWHTY5->o`k|d#AE_YQd79j`%GMS7FNvG3b7^Vy9 zn0HYCJy5MyQLoqKnW|JOp-?D*<2V^msZ>BOv0ANd2n7t@{=V;sZrQ>3c})5_%ms4z z7!qXwHHe~!QFj8aR~&*-3F?O|;#(ESIXP~Os%|~y^7c15*q5`gz2-5ol!fU92NIGT z_ves+>+Tf3gfcL?!nimYmR}cw*|BGULzI^7!;k#3K^YO#;!+vM@N~(99+<;fdqr zYPJm+pXYFYk;neQyXXEcTQDNQx57i`Okp9A#n?<7!{#tnKJdsF>utb@JH7dU01gfL zEK2hoPZAnO5+je3&^i*hWM`qCW^vLK!O*?U-#IvXV?#6koWqrwnD{j&K`7N>^tR3G z8zr1(qVOzcF#nF1&0MZ5C$l8*E^Uth0000zE0Ay_3@1Z_7#f-XWL#E{8Al7>L$ z0Rx7lnddoqAyfT%&#`$;v0@*5YdW3w z7mLNoa=FAshK% zDiy@zakyMAxr-H?iQDZi^!t5;Eno2A=?>mMx`Vg(Z!?<53LHLvfTPa`$mjDcX*Qdv zR;ylN4OH+m)fVX&Z#yZpUae;ss@a$K&})gHovkhr@w#xyPVlfVgXti1_357y%I-UHDvRWYvPEX+#g+j4Q9ayba zh7uQN1j%HQgA=Fp9DfODAU^*3*FCs^6IpO7xg`RUXyP)(;=d!ly=#I^l3e0Cub`{H Z`5PU3+D2e&<<>s`J(VpX#y^kqzQ;#=2x({YMw9Q&ndHT&`BD$#%Ql?{+)-OuSA`r}MWJ zVg+2Gc(GW}a=BERPNy^;kEz$|38dTYlFQ{%5S!g@|8f8D_!Nu9_Ni2glF1}xG8xi! zorc39&F6EPOeWOt_XS`W2H_Bo$MXugy}SEctJQj=(TLXTHL(jRXfzs>NF=0SHk;94 zF!&HjdZNX(3U3;LY64IMX__Xv%_wjLC!J2`0Jw?X=zPK$C$`&dYPDKaC={e16bcE@ zgun^<0k;ak*=xLE)@(Lqu~MmsFoMCLY&0Qog`NO(h@kyxaA%EbwJLy8sU*Vi`~52K zX0wrqW;_LmMq@evX4iAM9Od(Q0eHP$1%L|xAh@vrqB`HPQLon}f3aAka=9!3hr=O- z5F9`#J_7Jhah=U(4RjaRhkS4Xkk98kDz-`i!r|~~AQ1TFcDw(@<8g{aBE)l)PNxNE zI(RPyc>9e{@WGSMU%i7*v{!&P$WLz25)0oc=Dl-yy%xYZAm4b-rttL7UjR#%`#j_F R;_m(?iiXTHIMmcoLoO94I8;j@ zv^2DJ5#orqydFJX|Gm$_Bi_vyew+j6{r}$Qc@D1%fQqeAhJj)1!z4pP83k2MV2~s! zSt^w(<#HLFVBg_#xz1W8ioi(WY&Hu~6zil?DI^jJgu`K35(hkP)H%@Imesbg#5!Ps_$Ni*SiR8&sKb9?M`0-mH)gtg&YgRX#*TXz@Z+| z;|2H@xzE0TfuORhuO2k6#K8#sW^J`mQ0+E@$K`QkFV+DTlI$w{GJ;zid{*v9xeIe_ z$|Bp`@iKkgoFK3{4Z)#DWKV~W4K@5WZN+Ql_7%YxNqSx7%cWud&cX>)_PvD*UzxZg a%Kia9Rjz_59@~-t0000)l$0ECbfb-0$}>7z|u>IvuoHEmW&j4lzv=KA+EpIObc7e7{sGA)QVmnM@*^ z%|h38^m;wC+ilpk%>l#V5LCqP_y2_Cayd^XlX;j*r54R*lW!zbqtSpQNyz8(JVmWm zyV4S$2{Uhyc{Cb0QQbf{ZGT{Kr zvJi{K_&f+q^Pv4MK$hhS4TgFj_FD*rLOePdE-E^T7ZzTFCRUB`*?9&h(a#C!-v8lWG#k3AOJQaUey6Oasked^kDPe=Khg@7s584 zg`XfS1)&u*_c;I76#%`kkBfiZgKKo@0)9d6vZw=ExQUtV?eW{Y1Xv}=4X(2zy85d> Y0C^(qLv?Ui{{R3007*qoM6N<$f-gW7od5s; literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_edit.png b/express-server/node_modules/serve-index/public/icons/page_white_edit.png new file mode 100644 index 0000000000000000000000000000000000000000..b93e77600def75c9a144d3d0a5088a62c02cbb0b GIT binary patch literal 618 zcmV-w0+s!VP)$>5Y&axjp2O=VLu>*f>1L;s0)kkvKC!*u?s6CVL=HJ6oP~pNfZc; zsKr=bq;7MITw8NXw{SZm%59TId2x_9BQ zV86`NuvGI!>o^V!Na!=$7GJE{Cq`b+XwknM{UcGHFTTfmuS+ zm-zYC!P3+zmY;SG$?!fYkOih`QYaLxyF}A86h$GGN}kFj)_o*0e zjPMP%zTG7FYMAfO2Nn1D`D0Cj?Wl>5q%@CE10nX)KxpNmwk+!IWkzywiYD( zqUXiYYIq3qcRyMGJ;IY`(Gz~E$J$zu2+R{)xGlE*88b3WK6V*J>}2iPY1HH|tER0W z_+^^FdppY?o)Gt5M2`%xwRDH@R3G}^i1l4|6uchm0X0f!@&YdVLB5K&dd7Rv{)DXX zt^&vP;}kqj3f>94j+4xd93>s|Q!Ezi>?r8(Il$P}PFxSqu{d*!Y%*#cX(R0f|Juz# z3o0_xI14Al->1uky@W-rCI_%l&>PK^TXNSN{byMk2AI5vbwp!K-%-@!-vPR3iikL1L7HA!^!~ChCFU#lnGzp88=I z67V8PHBo4(l$u?-AKmT8?#_0rKW9dUNRbpLc`}piywAM9$xZ-3fR1C75T(BjCn-l* zjUcci2oXXo-}iqun@#)+`W@kL_-U&|2>MxZy~3IdmRm&8b)9!2%ksg3R)nNnT*TJOC=6{2hG86Dz+<^p6qfG5$i^UNUh+u)CD7O2 zK>Ioazn;U|+X0x$=feveYZL1W*Fm%e5P1sajd#eW#^5(ddx76*pt$^)b}$Q4oPabL zLc^HF>Z{8za;f$LtN0P$6C?1{X*jtXkRJ8IEeyiSzencvH3Ux_y>y^}wfJrRCQN#9 z?&e+C>sSAfrE%mZD5RfZ`gSndD)=P?+nG5Oq$zmY&-v+gc7R6c0u8^Ke#|XOq?gF@othF3zFpM8Il<8BJrWqBtF>b#_ye4{0)Xbu6j&@UIhRE002ov JPDHLkV1nWI9dZBw literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_excel.png b/express-server/node_modules/serve-index/public/icons/page_white_excel.png new file mode 100644 index 0000000000000000000000000000000000000000..b977d7e52e2446ea01201c5c7209ac3a05f12c9f GIT binary patch literal 663 zcmV;I0%-k-P)^@R5;6x zlTS!gQ5431_q{u#M2 zg&W%y6a}>qj1Z|7Vu&-DW6d~k-n;jnHsjb-q#u0C^W!_5^C=MlKq<8oNCQ6qS00!X z5eI;XP=g!^f}j{hku}E1zZ?XCjE;`p19k(Rh%^AQQ54xysU+ocx$c#f61Z4HnT#3u~FR(3>BnZniMIF4DouI8Hi4u>cAK%EN)5PO(ip3(% zIgBx+QYirR){Z8QwV$9Z(Mpt=L-Or3#bf-G@66}txq0yc*T(zNTBDT0T8rO^JeNbSI-Tzf5!pBioy4NwAN^?iN#{;fH1Jke4Xa`^fR8m z%h6dq%xX)S?7`zae))(Xst^Scp6B8FejQW?RLTM8@0=vnnntuRGBM2dpo>gbCnTD= z^<;=JuqdSf@O>Z8^XdR?s+KEfhDdB_#ahFj^giCtzT(s8kA$AViyTqaAR;KGaLzUU z<=GqA4bRwpX|IG~*x>pZ!@zLr`XQ`od>m(`;jz|M_*1GDO#$7;n74ppb8=eiqh760 x0yt}J1#p`gw$`o!R{d7zU9~!Un@nJV{4bstt4Au+Up@c;002ovPDHLkV1kWhGjjj{ literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_find.png b/express-server/node_modules/serve-index/public/icons/page_white_find.png new file mode 100644 index 0000000000000000000000000000000000000000..581843637079359a6a58fcdccf0763690c67b063 GIT binary patch literal 676 zcmV;V0$crwP)_k3`4d{s8lK_6bi^@vq&To98fNoK}7)fx$e2^Y&@<^jR_Ee+8}KG;X`@ z@bCyiolqX>bb1ZIs%QGnjzFU~L8H~d?e;*XP(h(S262}XyZ3a0h07r{KV?E70l+e- zE`%3x|M5#q+;HOC(h@A^M)7Rn13dm0&>K$j%k_F4wOWlsNCIH+!c_#{eS&TL8v4yc zcpnPEY`cQzZ$ILq{U-MA6Z6Z|1p!FZjQ}tXSb25J@HphEqX-6Hqo?-_Zn@{d#>2Ml zJGhxTAd&emK$lV-QK&VM&ix0Xy{GyS3Wp(+E1^8BhD3T0a)m-Lw@Lu4zQRrP)9(3F z^>$hh@N>OAXrmPYunLi|fJ$_*5i`46;M>~*5D{bp>-OL3{+!MJa`3kv~Q#QfQ%c z)1s}QE<_XaYBG;IuRF=td#+}fi4h(6HgoUyJLi0t(*dA^B)%@8kkG&bdM5P5^Z5WF z%d%>m^SbN0XeV)wbUOXn5Ag#A$gJx+7-OCkMM1S%MWIlTkbFLmOeW(&n&wUd&;`>p zVcRy$Z{K0=?SpNnP^;BYEEXleFbq(UY&LrXX$6qkJ~)8+b{=jj3HEXds;Z(?D%}}L zX3`39&dy=Zyar!ehA}e>w)(*vrCct{PI9^2Jpj&OZS8<3-@{0(gNv%1{)zAiLY+_^ zl}e>Ofd4&#Irj#7>=o=Uhv5IJ@?sN0^J|(WL2Uun$4}si6}TG-s3T#p&6GE<<2W)O zf{^Y2HlO#*QDvTp3v&d@;8*}aUC4lisG9(w7@d5Y8y)}U#FwCkqp*Mcgme4{&gGRf zlBfd`nF9cQBKB2_L{F8G2)7pAf$i)Ds`|}-c>pc^LRW{w4SQ)3N^BbZx)6BlCZts! zKph%`(m#xg-q3I7=(us;9<)*2%iuQ1J`oV3gU6V~T}^JU5714JN33&GwEEru0d}Uo U{MPL+lmGw#07*qoM6N<$f^vibe*gdg literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_freehand.png b/express-server/node_modules/serve-index/public/icons/page_white_freehand.png new file mode 100644 index 0000000000000000000000000000000000000000..8d719df5205f7415ce657e5c277db4533c82f346 GIT binary patch literal 639 zcmV-_0)YLAP)p{{sC7)XB-g4w*W1a1)XtvxrMYa1o?wn&v~3 zHnC|#(>B_M1d`_7gfzLiHy=0c<2kQQdXu*33(xYN_xYW39(cz9jEVT%VokB8|DoF~ z8u%Q5sdl@4VB7X#uh+v_;yOGY&pRi?378ghv)P1cngiAAb<}D#l*?rWDV0j_dc6Zk z-|P~AJZQCA=yWcQjG8fYnimzj*3KqTfN0Cy!G^$7)+bQ$+mHVd1J zvwOR^5Lm<|R+uyB1Nu4vL?d4qa3tn?9H7SZH@~u=fFHEDfSH|bHU6kh0O3%cLdyny z{`9S2Sw~WMy0MPy!64i`jdk4Z3>^+KIL_fN2V_d&ywBt`^IJpxUI$=YAph~5`;xCe Z{s%Y0vkUXDnO6V+002ovPDHLkV1loX8z=w( literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_gear.png b/express-server/node_modules/serve-index/public/icons/page_white_gear.png new file mode 100644 index 0000000000000000000000000000000000000000..106f5aa3611a4807ec8c21701c631730275089a4 GIT binary patch literal 402 zcmV;D0d4+?P)<@FR}JvtGRKa0_WfK^c7uXaFH3q@Y!Hnl8VySc`OtkPN3;#l*y*l23+99h*9JzA00}rAC!#M1dZ#v9YOBH|eC*${MmzzYjBu!!-< zK8tujf&(6i)1biy*F>4{f*Kd(IU-JsG&#b_@NgTnx@40)2@2%c;*=?-2Za=}O}7&( w%_K#(S>e1j&gfY?mR})n>>0+8p`iTe2d1K2h8#$+)&Kwi07*qoM6N<$f(2cptN;K2 literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_get.png b/express-server/node_modules/serve-index/public/icons/page_white_get.png new file mode 100644 index 0000000000000000000000000000000000000000..e4a1ecba1b60e54f3777717ed105cdde745b7184 GIT binary patch literal 516 zcmV+f0{i`mP)o)wchR-92qq~y6`XqbKmElbB3z{pkZs0VPF`CFvS?7jDn^mFo>d9Y&06* z&1MsS!M-CH3ee+h_sy)Ms%B*ec3R0RpVi9?*mU84yoq(Bw8 z<4(999dJJE!V%pWT~HGRIAb;(#O%2K3?uRpz}AfgE8e9q&OSdr^e^}lC$QXZz;S2A z)w>^oHy>?v)q--`!pmuBe96PxP0u*inQvyFW(llfv9 zXV1s*Jh`y2H%B3ZTA(AzpsQ?hb6_PyZ=c1?_B4fbl>G%!@ubJln=!)x0000#DY{xaiib^#X=YT4@yE_&2#eBulEdzjE`u&@G%2(&u{J-<}d(^uY4W_kMfEX z@!X)AR9F&FL?RJyJRUzvBoeqN{5kY`z3wcM0+du73~_0|*lac! z42Dw(Eg1o{Ash}P8jXrqN+1w`*XxDD;ShmPCZC7#4;wWbHoMvBl$=zF-`?*9j*Nbjd=v@OWt_BgKxP-3wd zy37?ATx&$b+&zRM!K;BD%Okw`Sb@&Pak8$KRX19jWZmC0&n*Ggv%j8nvSPDFw zEkV65AGOoBQ8kf`R|}Px*&INNS%osq9b{Fq2I(x6@xM>tg=vRLF?I`0rWzHyRc>}g~)F_Qn`A>)C_iwK%Z zrIJ;xR)UI1Y4Ozts|-Nho;q zVk9-bX)%F~!;63iu$Fk=VJn3~fmb5S@@)ZqjBT2{f`vT`b2}zxb0$o;EF@G3&BHK^ zc)`1kUzo^Qkk$?KFKHNBD?nP-MJ3b@&4fg;g5l2wMi^g?9qj+~@b;62o_U1_S1J`g z7m^UMg25FX1MJ5AQxAJ5F5WDt=$=-@JV-!LHA2vuxl9kN>PS8x??^AINH6LjF*#nbk4}=n3gfWp$kEX5IpHS zYiQ{@d7Nl&d$#+7-TckP&Q}N91e-C#5QQ<|d}62BjvZR2H60wE-&H<>}%WqH(_V;zPbB1rgSSSC(0? zWlQ#?N3UgnJ9m2C29w!SwoOo5_2Iq!<8vCyEoDoj@#oV($oJEg6Bj@;nD|2g8 s%L|>IZ381yx9RvPhV4J)*SeoEV4lyr#k*`nfWBbxboFyt=akR{0DpOPi2wiq literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_key.png b/express-server/node_modules/serve-index/public/icons/page_white_key.png new file mode 100644 index 0000000000000000000000000000000000000000..d61648452284da1bc28b10385f95b5d2bf027901 GIT binary patch literal 616 zcmV-u0+;=XP)-tZUVHjYHp;RjQ0M0pRlXN=mLv{hk9Ebp9&~+Wj-T9IkpzWPWd#fZ)d=zV^~S`;LE*!&u-?g42^wwN&Xr1~#d5ifl_2*B1OoS}CDno^8a50ArfE8;stQF>AP54J@H~%T zFz84s;dO!QJKD36(~!QOg!t_^gfFcSKDU4yK0+Ypg$NT^mIYcQ6bk*3P(lBLh7Df_ zTu=2xC#+-_%)|{Cv8zz0t|0y4D5M`xAc{gwOKc`ou<*&VjUREFHs1qd<_xSkKeTBt zgyCi=@jj;&Ns^GsWWaIUl0Y2azcDlF@u{(P*!+EH;lnU~b|Lv{4|4Hdkh!qoQHiE$ zY#y>KFA0QEw=4Z|uV{0A^`Y=D}hB$GP&<$bi8q(u;p^0(my3Rz7fP}|# zGZ&#uor4@c3q9r|f?H6-UZmfgKx(iV(MQ`MPWB>iC~SxnN5H*zb*A3#zWwgu&c|}3 zn^g87H{pdeasl%Lhmab&jC?lES}7C?4BFDNA<}20hoY@w_IU%i*T;}}wh!589}7~7 z#Ug`-R~4j&+K_y4kW@X7qLr-)S5qVKU)tO;+kXJ++{vPI@{hVK|PhMVVx_`)vx~zUs}c9O-Ok{00000NkvXXu0mjf DS5_-g literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_link.png b/express-server/node_modules/serve-index/public/icons/page_white_link.png new file mode 100644 index 0000000000000000000000000000000000000000..bf7bd1c9bfd78d689c73ba67cf914182933ee68c GIT binary patch literal 614 zcmV-s0-61ZP)OOAS;jTeL{ZSdz-%)SMH9tDF;N4B6%j=d15J&5qy`F#vB?Ar zqS1nH@%ny_XSI*Y>) z1f5QYdmzT>YciP<3WehS<{GovEaLGv27>{*-7f0&I$yJ^L%ZGPv1YT$V|u;*+ZCWz ztHI~CDVsuy($SfR6-`N~K?9GTB#l%%0h7 z-q`K-y~E)+s8lMyTrPL8^_pUo)9G|SluG5pPqw6!LJB_PzyJUM07*qoM6N<$f^=yZ AYybcN literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_magnify.png b/express-server/node_modules/serve-index/public/icons/page_white_magnify.png new file mode 100644 index 0000000000000000000000000000000000000000..f6b74cc40f82fc83e4dfa6e9647ccc1b34e6ed7e GIT binary patch literal 554 zcmV+_0@eMAP)Vb2f>2}Fa82O3m(Ob=t*sniin`NpInLyMJgI`saru@YOPfh zy4g0#G*cV!#N%;Gq9_VH9?v%kjS3Rb1j8^;C={$Gp=lbj z*(?%?geA!5^Pok%UauwjA)v4g2`HedDw4_Mk4hhBQt?e7YJ5(hcj|3dNu^TOPGnjB zTTsqd3GIZ=Bb`n=7no)dflv&K(lsWw?lH6T1Yht0F9qgIuzh}ym0%n<3d3EBWB*pg z+G!I0lbAEXyd>k|QNuwr4=KX1D+tLPv)j@C1=N4sA4NF9A>HcO3G47*Y6!+SrUH-7 z1hb;^#S=r|`aMh>J#dWruAEf}gcR(DRUC`ZUev&$Sbh0SgLiTXeeHEU<$_YV;9281 zym`igIE%Sm8DpDw7@71Tv^EB5xSdUR*0$Mqp+Wq8OoaZtOg52&)zZ;;M=7#C1Yd6x svjx>8ad4e2x|*xHHwRjcjs6zA0XLDUqKT6dS^xk507*qoM6N<$f*wetruo^Ag2=LamM1T#~4RmC^m`_ zs}H7d&XJ}mg+hU?tu0noRvyjI&o2SRAeYZFesYkts79I^jJ7!A7%6nJwq8O?iT55M z1OQ` zbL{!Cp5o*IRmE9PInMCSPjTwfT~J+EYkz}tjxY=fg5Yf6EQ@DG$0kMJ9h^&$W}9BU zP1oj2;?MWVkKIEl)r=Y;L^Cx2q|>!)qJJ8zE7-V*-Cf7V8_2#1c0N975t~+&QUpQJ z5(uo(-O_`%Rj@U@t>JYAgd!>L?0Idxtd#oW2gc!jinsAEva8|kF4#Ic**mmml_{d^$s}Q5Q)KCys4sfck5bP1SyeHwh2`A<@N&t2j0^lgHC_^(pAAPCNjwl+>AN%C4Ll>_8Hjda%9 oS~i=#*e)>KsPlg0=2)Qg6BCqJ=F8HdGXMYp07*qoM6N<$f@i)wr~m)} literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_office.png b/express-server/node_modules/serve-index/public/icons/page_white_office.png new file mode 100644 index 0000000000000000000000000000000000000000..a65bcb3e1e9613cd9e4950850db43d7025a5fdf9 GIT binary patch literal 779 zcmV+m1N8ifP)JNR5;6x zll@CmQ5eTZ^k*a#RQf}fVOdd`5NJh6S(>6Cf$wEW#f&JyAR#GAn9>Gml;nOf3WCDa z5({5&UB$(IF?G#$x4X@Ickg!Y-HU!Z_rzX=qAq-XI_LS^=lOCT0|0{#{kBkYDS7{3 zD`iu%E=`cDX_^#^#n$5SIQ|4Zhsk8>N|zXHXG@*41$i-7`Jr{8`3S_OEcmY|RF48wXkk?WpdVM4OePBSbfh z#4_=eXJg@3epx~gi>QbUmO}Bm(ENN3+@c?jWiKvSrm(o|W}Ud*?vy~fn1!V~Cl4kB zI-;c!8f~-v)jX82%EG($>?;KSD$64f2&4qQ#=Yyrcpy$57RAVuV#vKMP)0hT$r6m# zc^F^XaJ8R9Q|}x^NoJYIvYZkq-z}Tnj@UJK2l2H zG}p+VvtjP2Z%bsb$~7QLJ9#pC0dKi`ppOd^_V;ME6tdzC0PtV|r=@e@37O`%0k^=5^`%cf$eu00N17Ro!{^30krz>a%3j34C?*{Mt2^a4~ zK=P+Qq%|f;Tc&+9ps;@Mw`EE%rgs&#y=j6BUGg96oIqdwj9-fiy*N(|@o)eD002ov JPDHLkV1j#pUPb@_ literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_paint.png b/express-server/node_modules/serve-index/public/icons/page_white_paint.png new file mode 100644 index 0000000000000000000000000000000000000000..23a37b891c2f5faa3b8128d45373ceab794ca609 GIT binary patch literal 688 zcmV;h0#E&kP)PK^TXt2QS_@2qt2T|9~baC-vaPn=ziepcfAwB$0!O2Q)E}1e8!q+9)KT5JVKU z7HNY}h##OS-BxWHWjD0wrPDeEfUClHs%Q6&2u@FTOJkKMQN|_Rlw6rQz$gPzqGNtj z#ruSeFeh835JJFiM6vp@6M5bXj%k7CMt%SIwfbF_fD-3*Os`9Ly_Q3WQ_SX33E{pX z9_WIeeTCGQ3wYALpBcK+P-iuw;3i&7xCua37k5# z`>c`M@sGeC7cdsdz`aE9lOz!hPholbyz%T85LYf6O*@SA+9&+^7k>+4M8$A8iNQq{ zQvn8k?-+dU`Z@gK0z$EtPV#+`^OH`R@cE-cuE&_!D)SZGxmQxeobP_Zwq zMEgi6ePN45N`|V1so0uE8^}1xw8s;VM%Ai@7} z2-&Cyvez_-O4?6uv{zTaj|YeYEk34i~K@`8YW2g{x* zc;7z3lItpVy_et{Z-ZZ)<@*%{l7Ao8mu@V7*gz<_1##mwW*%LEwCdzNsVLYx2*T-J z#HeQ*_a=R~KDdVNk$EVgAIRl$oQi_(`_IrdJciDpH|Xe{K-YsMtc!cRnFi$qzsr4z z5*$;ecov%3->1{YNy6-Gf(Ecy&_I$CjI#laeuE+S120^|Vjsf)W&i*H07*qoM6N<$ Ef)^4A_ab^avY?n0hpS-#mn_4{O$e%cm-@NH=3`90Wq+3`~HKArSdfX`&Z12 z(CY$VW-MNtXX4xy%yUeE?}*~0-|iByA@ZrwXgph4S*bhcc5{HB!DFVm_v}P*g7+Q~K}7K0lcp(^N@X>U zV`{ZpeIf${R6Hgg4FL^`X$Eu75k(PE6ycl$AW0Ic)#@rR7Z(7;V?i-dR1K935Jgcx zPfkwK>2wGokf!Nih^ARp6-6arYFG#(9Ta!x93nFEjoA==z(g?#sDg?Owk?Mg7K+>l zWYsf(<`#+$h9Sp6gFOg_dd+80SkUpk&xM7h0`Sov9W73spU;GP073|VfZ&Gd$J$*0<~TV5aPS|qWH57|VJz+d0000vYep8SaFV10Q$h+;hIUPX_=v5b}%>Tm<(&j1&5;I!55C)oN0s(P%ZB zP3Q#ahfpXKWF@S?jm4U#fv)QovMhrriclyNs6-G12#3R##4PSZ0VY(dRWJ;Lwuq{# zAW0Gwi$yA^R4RZ!;W+L`f&%x{=D^VK#BBWL4Ys{;*!A7Q;!=dN<&D8*GzGaF4`hV4 zDbY0{NrMX>ZqF=0((gR5-zL$kC*b)!fwu{Euru|XrG<$^n#@)7i_>rCmRxnDq>$Y%gJaCkRd|tE*a2x05Pe!I^e13o69#&RQZ36s0 zB=O|K2Yi(jsMqThn}9t?f5E-)L^naZ+db$&%M$!bCdm=jv7?t_lB?3&%Ltq(>ESw? c;MI421LCcoDG!2@;{X5v07*qoM6N<$f`UZt7XSbN literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_picture.png b/express-server/node_modules/serve-index/public/icons/page_white_picture.png new file mode 100644 index 0000000000000000000000000000000000000000..134b6693687b2fa5fe36d48a9c0b8001f937c741 GIT binary patch literal 650 zcmV;50(Jd~P)VHAd+bMNh~)LLRqN>D)-jd9UvB%+hyKX5U|&4t0)fzgD-MPpQ$nHU%yoz=vI zMGb>1Xu!6Hw$NT~@Au<4P-+{9;Uw?&oj31uzH>xX0T7Xkz!(tn|Ed9-s_FqyReC13 z(ll)vW1O{Ck5ihay12Ob2ABc@RUI;zHpaMiyRDs0r>|D4rHw{ItJSJnYjt~jTbGuW z`X(~}?!&86q40R8<4zYw;$qi0^3ec=c&<&H;r`8W%H=Xymf^i;Wo6~<+}zx2UMzpC z*6MZN?(FMv`n|KO3(KFiUaucP0;Z!@LcUNa%8#vGK5aZ>wDgB0Gi=t*argWJcdlMQ z2#MpEX0wU+9&0U?N(F#OgpviU_Y{jYMsj65U3|PjwUOY}lUYj?MTiK_Il}NCVx-Eh zDx-TzMk7se+M#W_>?A1-x}ZXw3kkyz5kW)_hkjsi@RhKadN#H$Hq)$07*qoM6N<$f}lhwPXGV_ literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_powerpoint.png b/express-server/node_modules/serve-index/public/icons/page_white_powerpoint.png new file mode 100644 index 0000000000000000000000000000000000000000..c4eff0387d5888c638ba09473ba6d2369f7b56f0 GIT binary patch literal 588 zcmV-S0<-;zP)HU2HvUSp%6 z*n}iP63IK?dpo;h@sj9~pcxo;VVTc-XLiP@DgefqE#NE=@oyUd-&HjLpsLIuSFXV-EMck)oQ(A`s%*^&wf0(rNiNHsU%=0Rw;WC z(kbc37l6fo`-0uR!pYkYv8U^3?nsh^@pw!K0TH3uYyx1_2>|JbXPmfskJ|1YAw9w! z9`N)1^Aesr;y5Nr5-ODn)oOL|CGi}f9!&iVwpK$khlIX10X$H6^A_stBJqvLhU$?V`QXqKme*s~gVDJ4A;LTs_e15jhc1;By a82kqHEPVYFAD2!50000JNR5;6( zlS@kiVHAe7MZY2;Xi-5)WxDDgv@tCUl*&p14T@Z~3ThM5LP4tuQfLu@EnG;nXc<8S z6&3BN?fx-cv-Kp6>HRiNTHE>$X( zD&=w+?GWC>?RLAGC6Yix;an~UmSt)tSf}1VS6N1N2ONORdD? zaj}w6DAZZdOud9Ep?M?{iQWbE5^9HLLZZF|1kdy0Tu4InEuboP9@nvbZ-P0n4AZTy zyMRIxRDmUE#LdqYuD=-Qz4N^bC`_#S7vcLn1M}{J(Wl3#c4VWczu&)AjUlh(11>gp>f`wv{KnjF%!aA*Jk N002ovPDHLkV1kkt*XsZP literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_ruby.png b/express-server/node_modules/serve-index/public/icons/page_white_ruby.png new file mode 100644 index 0000000000000000000000000000000000000000..f59b7c4365fa1720af1aa04eb47167ddaa6eeed4 GIT binary patch literal 626 zcmV-&0*(ENP)ZS(e|#C2>JN4>y}l*tQ*E7zP@R2CCJnkW?xa6bgk%(hgtZ z0=~d?U3i`+Mvi4!&~+WPT1^NX#{u6&QIx+DE(oR{&T5&-ovF?@wGw)P&AtpHZa|G%V*GUUqL@@!d4V$`8=##4)ytY959JG zdc&Kho)&AL70^i z!PEmeeDWCB-UbK(*4JST44^tV2z_J(dn~+vBMJT97_7rzFio=~XczIv?PQ5$v%u~y zu(bteXb5I1h2zCV{Jc2~V{{yzZipgsP6;k264$*#5q?GzCm|CPa9CKqm4b116h3Pu z?+%Cm52plC8|5P0@igf2GV1KkCfk{Zecu=G@VNrf>s%g9c5D%@cfxVb6$nY`1IW=4 zt10QqSps_2JLp0f3I0j0u>#qA;v!+T))KEbCg|mo3q0pG{OR}p0fPds8+K~d>Hq)$ M07*qoM6N<$g1S2e3jhEB literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_stack.png b/express-server/node_modules/serve-index/public/icons/page_white_stack.png new file mode 100644 index 0000000000000000000000000000000000000000..44084add79b9a0fc3354d16bbd4b4b5ff8095da7 GIT binary patch literal 317 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6SkfJR9T^zbpD<_bdI{u9mbgZg z1m~xflqVLYGB~E>C#5QQ<|d}62BjvZR2H60wE-$R@9E+gqH(@-qA%AW0|7U8+xDRI z0k`B18}ImRw2g{jTGP$Pmx3yI6F_2s&$|`cJ!i0UN zB3H;=r{#{FwLaNVJ&hZl9+MTHGx1T^-A=Q0?hRb#8a~x50X%;`b6ik3cw=#XdxWy= zgrpBoDjpwP&g9<9h3x!k_B!?vuTJVkmIJ-U N;OXk;vd$@?2>|rNdMN+^ literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_star.png b/express-server/node_modules/serve-index/public/icons/page_white_star.png new file mode 100644 index 0000000000000000000000000000000000000000..3a1441c9a12062a4bb3d706000d3ca14399aebca GIT binary patch literal 565 zcmV-50?Pe~P)SCZIX8XZzY2l?gCw6LlgWJ5Avz#QX4|&mI8LN)w~J1vgL=KLAhlWz*=#m~gyvxa z&;iC6gb?aZvMdXxX`<0+D1hs_pqJ!wxqlEH;CJ)je~uL(gpi@v>!I0f_Kl=E(E+Tq z26na*9gribxx-Oft(HnstyXUUy!39&E-cI%J5Rsy;(PGZH{g{ty!HVC&yGPT3H8x# zw{^gBPW)O0FMoh{k%l<`1a|To_Wl&u&-GXm8izU|&<&utILc4wc6s@u1bmTz6x{qg zTw@7=FQRcg&r`h+gcR$*Jbv+*DPk7v)B@e0o2 z6IlBXW&8xh@9)YKiV~2>+z&XKd24JT55YWz&JtfvCg4r^~bLP79-yS@n$OW00000NkvXXu0mjf DStt2z literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_swoosh.png b/express-server/node_modules/serve-index/public/icons/page_white_swoosh.png new file mode 100644 index 0000000000000000000000000000000000000000..e7708292adabf4821612bfca032cbd019c63180b GIT binary patch literal 634 zcmV-=0)_pFP)KrcWDBzIw9XCtIF5G<@j zP(;CSqHxUrerI>~wKyloM4~t_Ofl@UFEj6$Bmm6p1aK6H{5zI_FOn(%k{CiRq?CT< zoV}Ey-7=-5nVFes;1m!f?EqZLIs4k$n%39XN4dPbtX{9DZnvvaiWV0aH9I>yf;2<< zHmo7WNC<&iE4ji-iKJpsBApDKiAiqWy8R$FV|M@E-RCB03vjWNGQZJxKCc-cSB=dq z#v3snoDMC=4<2BDgiZrv0Veh~mz(X=S@;fbe>CJO_5|oe2o3=wgfW(StLzI-qr&kc zhXEJ?9=`nWXzrUKL_p*Kr9u@95MU9EKqp2vi+%&1&gUn&>Ut_d3>wiyiAJg5G7j%G z#$sf%Kqau!AAHP&4Q?edl!FWqpT=C{D}$15WC#5QQ<|d}62BjvZR2H60wE-%6;pyTSA|c6o&@eC9QG)Hj&ExYL zO&oVL^)+cM^qd@ApywS>pwx0H@RDN}hq;7mU-SKczYQ-hnrr=;iDAQMZQ+*g=YOM= z!QlMQEn7FbaD->uKAYgo_j9)W&$$zS*W9}m(ey0q$&7l-XEWO0Y(9M=SnhLbwy;d>@~SY$Ku*0xPvIOQeV1x7u_z-2-X>_74(yfh7C znXL|3GZ+d2`3re2hs?MKC#5QQ<|d}62BjvZR2H60wE-$R>*?YcqH(@;f-l!01CbW>s1Izr z3LkoHh<3E?TVANoG4CX|$empRCCS=R(U(hVJfm~E?IkDKRK&NP2|n`v>d(vV;W1uY zrFGVdwn;4b{qUtE`?GB`)E1ga&i2|7ncUL1b!KMq^QnT#_gn?_Z8(c`1Q~Vy3oL!N z$M8vHL&U1J3SJF!56azQU3B6>r|ZQ{U6)pC|tRy7$(5JQ<@7eB8yk=XcNf-aBIe#;8c_B$^=N z{-Iq&o3%O}V4~G($=zcP(LI|+6dq{?rby~MXwJQ*=!bOvl%?k zYY;jP^@M_k03MHL+-9?_3W5MN=moFW3xmPHU=-4Bw;62MrIhg_lwHEsv)V9U4x>+9cG2kIz8fWo`WyMMfz zdg-)p!<(hFR{VYSDJHEJn09O@#)%q0l?GUg9eS2~vKPUtd+=ak5lWLd-jI=;cjEf# zt$1;~?G!t@s+VLwL=P+Ks;E z!Jkh#NeohG;&02OFD7^EY zP!_PL2~i9VnPEW6Fz?O3dVF_U$duAL$=SU7&hNc@-drC5A4z=IgjR%B|D)?dOEaGb zuwod-$hPex$8oSoqK;@Z8u3EBfK@V2CKKqo?yA%2pjNA)(P%)HWf#)x^$?52W{|1b zPXOA$IfrSQV2q(qC_vLR)a!L9isAxjoeoJRlgE&G0Ga8krBVsGjZJJ-x6y1i(eL-q zwB%+o53no?l}ZJh#drAjlc6nhs3RTn;1IH+x;K#|X)!=#fM76)$IqT4^N}IF%aQ#o zTKS@*)|#L#jiCPi9~);c`x>TR|0{+9a?O5Exg#~V5W2C7G9nAAN(~f z2caqx&t~GhnK;qW3~&OuEke?%u(8Jxs_+ZVVz1^-uLrP95TahadGG$+(D&+%2QMF8 eFxE8s%l`oWamgLPAe&$S0000dKE@duOisOkyZ-5 zuwDqkAi_*y5o3Xrq7ieT<<3p#-R^dGySwea-CgZZZITBc?#1u+FtBuUCJUZe;~j-%Tu@ZpYB;$&ydfdZG#(j;(iB#^yRlqv#C*LO zXWXM0cpKKBlj#L6awm|;A38Zs3mg;sQZmCAZT8m@X{AlP6 zVI=SsiA16x=>2%^XV3U0y4~G+MNE!B{!#;~%L2l(14PX>EblXb{rnCSlVKe0dyf-O zuY#uOf}m&2xq80;4d3i|cuNw}U@sg3VKRU)>Os_1L3pl5mK*|?X3#a}K+EVZt&w?w zefXKP^ZqnW-3y9AhYJZ~r4m*!Z3OSz3d}2Q`nDM_f_u>L%8Cb}8`?bl)x?gwAy>zp z06y57kT6sry1g2l{|V%UW?)JwnbzUugbvpOF3=oZDo}spfs2EWKOH{_^59;ue!o^A z@e7dWS|QI`Ff-E$USJ`LqDF}zH%R}YOlMiv63A=qK^d}n!5_(fW%^k4U_D`_meIDi kNMKea>saR;>gt<+0gk_zsk5>Xc>n+a07*qoM6N<$f>Jg*?*IS* literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_width.png b/express-server/node_modules/serve-index/public/icons/page_white_width.png new file mode 100644 index 0000000000000000000000000000000000000000..1eb880947ddf3e745c29e8d9dc90f09c7e6e323c GIT binary patch literal 309 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6SkfJR9T^zbpD<_bdI{u9mbgZg z1m~xflqVLYGB~E>C#5QQ<|d}62BjvZR2H60wE-$R?&;zfqH(@;q9b3Efq-lM(nr^( z=EYR73-9e)UYMWsXy%?aZsD68Yyv^2$~6QgEcljw%kx>O(f-gQ?@fOOx3A-0+Qw?O zRx~W)kn~Qe2d6f9nMG#g9Q04Mk==M~N!Dglvxk!fgVh#w@ZV$IY1+Xc`d{d2UcaP~ zfWp)_Ivqj}l2SPy^9ZWy6rG9Yx4v67_uA&&9|XA~5-#3)W3%em1peD8RWH^#O%XoM zxMPud%}GTj#~*+7JMxTd!`{^Q+>(D3*|@KV`*G2;{QnANOxu1$r2xIe;OXk;vd$@? F2>@zac~<}c literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_word.png b/express-server/node_modules/serve-index/public/icons/page_white_word.png new file mode 100644 index 0000000000000000000000000000000000000000..ae8ecbf47672a874c0958d0d113a56162c2bd364 GIT binary patch literal 651 zcmV;60(AX}P)hkjP zNW|QGv-YFNLN^qH@tJycPNG5ti6B7;r4mEr#lr@*T8*M85D`{ZR^BWwF23T<%MYIh zdC)S*p=|xk^!~H=+HSZ183~y8v4|mYmZxt&)5{{~>J`>E223Q5>T$=~mtA71q-jdG z+eJhOAyBW^0k9Gk1+rX8)zFx((CG^&tDY>6XaS~Fy!WJON|Gdujg5^~Vzt@o%BcYLiNiTQSD`zL^ociBz_>bDlpw3kriQ@Z`bVsGz-_6N>$&gTDiKDTKR^ z-hB*tHa^>!oD~5TK^0UK5rZ}RBm50Bv}S-yA%s=Ha5RYb{)!z2N&$&64gfhybBu8p lh~_|?8^bu;BRYt{<}Yrwd83Y=s?Goa002ovPDHLkV1l%3CP4rI literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_world.png b/express-server/node_modules/serve-index/public/icons/page_white_world.png new file mode 100644 index 0000000000000000000000000000000000000000..6ed2490ed1432d5d667a76235360824a1088e928 GIT binary patch literal 734 zcmV<40wMj0P)JT{hN;C#tgf#9krG=I>5!<*aE1_(spcgF}<`n4i zJi-}^6UUeU4jUFwdCiVPDm%`Zx^UBa8J(mnR6wEgz^}o8;)M*Y(@l_!Kfv)}4+NuM zaPXE50z)r)9=D=SR|RIqfQ^j}Hu!fzMeQBo+@PZk1G8hOw|vBTvkx`HM)Xe9q3xao z@`p0`NO!2904FHSLA6E@Y-O6zH$DQzvq@aHsz}}<(!v(Z_+EodX%R&NZW75g+nENo zV0020rxE^;7d!067AN>6*+&YLp$9uH6F-=In`XC{Cn%+o|5)b&boEPr02w@|P*oGm QmjD0&07*qoM6N<$g78X0Q~&?~ literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_wrench.png b/express-server/node_modules/serve-index/public/icons/page_white_wrench.png new file mode 100644 index 0000000000000000000000000000000000000000..fecadd08afed92536be91ab12d8e37b6bf410d5d GIT binary patch literal 613 zcmV-r0-F7aP)wK%m(L+9IV|s|#(WRl-O^4GvaQsnHq|OstfO zIJ3}3<01}YGARE4m!7=)QisvlHUo!Qymx-@-t*p_129Ko-#pVI)6#!*kLj-AGXWNR zyA_{wKii_amK7^YT-v z6#plaNm#8`-kz@OvjIt^4%IN{@J3bR zRI}ME1Mv85p|%;RK>ViR>APPLB4;;BpCtqE@P+*7!G>I4UjNx~e>r3HA^tWCQ@S)l z{BslcSwL-CxQ&_ZZSv_g0Tu{yi*X){Mt|W7)lbE`SQxFP00000NkvXXu0mjf;)M*S literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/icons/page_white_zip.png b/express-server/node_modules/serve-index/public/icons/page_white_zip.png new file mode 100644 index 0000000000000000000000000000000000000000..fd4bbccdf1643f4ff5022fbc59b82546e259317e GIT binary patch literal 386 zcmV-|0e$|7P)_QM!1S$Bhw4w+iRuFWf;tfR6D%SMJrb+tx zC9R6{2>Ou6#juIy6u(I?|;&Owi$sRB4^20apB5xE2 z#B9XekY66S6lzfCL!eEQRgo0LokTA55@Y#%_wN!TXPw^Q4IIXsG~v#u_4t;x_HM16EQ@QRY+rut&97&UefsPmLrQ5P zBC2kcbux9L%2bJz$P$XV$*zSxb2e@6_3O#;&!FD<&hLjGn%~%en;7)djE^d6!t$lW7GyIOKlQ46hr`Z zjLNuRDP_53dNoN?wd&HMgL^m1DXFU<5dQsrceN>fSz00000)O9XRTN^$%%`*Fg>ryDtc(lF@?b>dE!20r+y z#Q*>(wbV5H`-E4Do={CJp7=ERhw15hgZi)?jRG88 zzVz(5;g?Td1izJyO33bhjg2Qc7FVY@f9!o)Gu?DII~vm-Dc?}3M!fsgjP?F(7`rgg z+xOk8XD)e?Zl=5+un`5!7kr?F=eq)K-5uqr%yU$1hLv){Vlm=)*5~`lwMciiXFu*g z)*Jkz6AF>#zb(Vx`Iv{bdGZHtlW)v(y5k^|xgSUc9%0}S20nrYrO}78ofk?bV!5)4 z=Ngz@+$9N1>>mA%IWx`Fqa240bWkiW;2TZgd8CZS0U}@mknC;!2;wi$eI@`h0y2JS`Eae0CW}q(2(%!m8 zWq$`PDU>LT1_y*bBv#P5<@q0@ttz$hIH}YMDvAigCc=y*)jY-VOpTd;A8@3t7Xh4r z0KTWOk;N2Ox4!&&^4B*no$WtTX!BXB)rg!y8dvGgKBQKLJNXRRp0}Bsjd1|LNQX~c zbC~fjrk2iL@4dYF*vt;}dFn(%h)n_-vzEIHMOKRkdF%3Lq|zBgKm_h>TEq!))nWjq zzn;B!?!(dQcHu$#=JF`cS&W~C`WHFW^B!~MI#k)>1Vk&eQy8P1O`J6V04{D@|7d6^ zyBABnh-d^H0FX&L07M||E0n_dp4v&Q%PSE9p#R#Hq)`5I_(B5CE#q dxjPz0{s-<+c#AC!i7@~G002ovPDHLkV1iPlpuqqD literal 0 HcmV?d00001 diff --git a/express-server/node_modules/serve-index/public/style.css b/express-server/node_modules/serve-index/public/style.css new file mode 100644 index 00000000..eb99dc9b --- /dev/null +++ b/express-server/node_modules/serve-index/public/style.css @@ -0,0 +1,257 @@ +* { + margin: 0; + padding: 0; + outline: 0; +} + +body { + padding: 80px 100px; + font: 13px "Helvetica Neue", "Lucida Grande", "Arial"; + background: #ECE9E9 -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), to(#ECE9E9)); + background: #ECE9E9 -moz-linear-gradient(top, #fff, #ECE9E9); + background-repeat: no-repeat; + color: #555; + -webkit-font-smoothing: antialiased; +} +h1, h2, h3 { + font-size: 22px; + color: #343434; +} +h1 em, h2 em { + padding: 0 5px; + font-weight: normal; +} +h1 { + font-size: 60px; +} +h2 { + margin-top: 10px; +} +h3 { + margin: 5px 0 10px 0; + padding-bottom: 5px; + border-bottom: 1px solid #eee; + font-size: 18px; +} +ul li { + list-style: none; +} +ul li:hover { + cursor: pointer; + color: #2e2e2e; +} +ul li .path { + padding-left: 5px; + font-weight: bold; +} +ul li .line { + padding-right: 5px; + font-style: italic; +} +ul li:first-child .path { + padding-left: 0; +} +p { + line-height: 1.5; +} +a { + color: #555; + text-decoration: none; +} +a:hover { + color: #303030; +} +#stacktrace { + margin-top: 15px; +} +.directory h1 { + margin-bottom: 15px; + font-size: 18px; +} +ul#files { + width: 100%; + height: 100%; + overflow: hidden; +} +ul#files li { + float: left; + width: 30%; + line-height: 25px; + margin: 1px; +} +ul#files li a { + display: block; + height: 25px; + border: 1px solid transparent; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + overflow: hidden; + white-space: nowrap; +} +ul#files li a:focus, +ul#files li a:hover { + background: rgba(255,255,255,0.65); + border: 1px solid #ececec; +} +ul#files li a.highlight { + -webkit-transition: background .4s ease-in-out; + background: #ffff4f; + border-color: #E9DC51; +} +#search { + display: block; + position: fixed; + top: 20px; + right: 20px; + width: 90px; + -webkit-transition: width ease 0.2s, opacity ease 0.4s; + -moz-transition: width ease 0.2s, opacity ease 0.4s; + -webkit-border-radius: 32px; + -moz-border-radius: 32px; + -webkit-box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.25), inset 0px 1px 3px rgba(0, 0, 0, 0.7), 0px 1px 0px rgba(255, 255, 255, 0.03); + -moz-box-shadow: inset 0px 0px 3px rgba(0, 0, 0, 0.25), inset 0px 1px 3px rgba(0, 0, 0, 0.7), 0px 1px 0px rgba(255, 255, 255, 0.03); + -webkit-font-smoothing: antialiased; + text-align: left; + font: 13px "Helvetica Neue", Arial, sans-serif; + padding: 4px 10px; + border: none; + background: transparent; + margin-bottom: 0; + outline: none; + opacity: 0.7; + color: #888; +} +#search:focus { + width: 120px; + opacity: 1.0; +} + +/*views*/ +#files span { + display: inline-block; + overflow: hidden; + text-overflow: ellipsis; + text-indent: 10px; +} +#files .name { + background-repeat: no-repeat; +} +#files .icon .name { + text-indent: 28px; +} + +/*tiles*/ +.view-tiles .name { + width: 100%; + background-position: 8px 5px; +} +.view-tiles .size, +.view-tiles .date { + display: none; +} + +/*details*/ +ul#files.view-details li { + float: none; + display: block; + width: 90%; +} +ul#files.view-details li.header { + height: 25px; + background: #000; + color: #fff; + font-weight: bold; +} +.view-details .header { + border-radius: 5px; +} +.view-details .name { + width: 60%; + background-position: 8px 5px; +} +.view-details .size { + width: 10%; +} +.view-details .date { + width: 30%; +} +.view-details .size, +.view-details .date { + text-align: right; + direction: rtl; +} + +/*mobile*/ +@media (max-width: 768px) { + body { + font-size: 13px; + line-height: 16px; + padding: 0; + } + #search { + position: static; + width: 100%; + font-size: 2em; + line-height: 1.8em; + text-indent: 10px; + border: 0; + border-radius: 0; + padding: 10px 0; + margin: 0; + } + #search:focus { + width: 100%; + border: 0; + opacity: 1; + } + .directory h1 { + font-size: 2em; + line-height: 1.5em; + color: #fff; + background: #000; + padding: 15px 10px; + margin: 0; + } + ul#files { + border-top: 1px solid #cacaca; + } + ul#files li { + float: none; + width: auto !important; + display: block; + border-bottom: 1px solid #cacaca; + font-size: 2em; + line-height: 1.2em; + text-indent: 0; + margin: 0; + } + ul#files li:nth-child(odd) { + background: #e0e0e0; + } + ul#files li a { + height: auto; + border: 0; + border-radius: 0; + padding: 15px 10px; + } + ul#files li a:focus, + ul#files li a:hover { + border: 0; + } + #files .header, + #files .size, + #files .date { + display: none !important; + } + #files .name { + float: none; + display: inline-block; + width: 100%; + text-indent: 0; + background-position: 0 50%; + } + #files .icon .name { + text-indent: 41px; + } +} diff --git a/express-server/node_modules/ursa-optional/.travis.yml b/express-server/node_modules/ursa-optional/.travis.yml new file mode 100644 index 00000000..d699c4eb --- /dev/null +++ b/express-server/node_modules/ursa-optional/.travis.yml @@ -0,0 +1,19 @@ +language: node_js +sudo: false +env: + - CXX=g++-4.8 +node_js: + - "0.12" + - "4" + - "5" + - "6" + - "7" + - "8" + - "9" + - "10" +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-4.8 diff --git a/express-server/node_modules/ursa-optional/LICENSE.txt b/express-server/node_modules/ursa-optional/LICENSE.txt new file mode 100644 index 00000000..55e332a8 --- /dev/null +++ b/express-server/node_modules/ursa-optional/LICENSE.txt @@ -0,0 +1,194 @@ +Copyright 2012 The Obvious Corporation. +http://obvious.com/ + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + +------------------------------------------------------------------------- + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff --git a/express-server/node_modules/ursa-optional/README.md b/express-server/node_modules/ursa-optional/README.md new file mode 100644 index 00000000..0663f13f --- /dev/null +++ b/express-server/node_modules/ursa-optional/README.md @@ -0,0 +1,596 @@ +URSA - RSA public/private key OpenSSL bindings for Node.js +==== + + +[![Build Status](https://travis-ci.org/JoshKaufman/ursa.svg?branch=master)](https://travis-ci.org/JoshKaufman/ursa) + +> NOTE: This package was transfered from [Medium](https://github.com/Medium) and [NodePrime](https://github.com/NodePrime) to [quartzjer](https://github.com/quartzjer) to [JoshKaufman](https://github.com/joshkaufman) on 8-2017. Pull requests are welcomed to help maintain it. + +-- + +This Node module provides a fairly complete set of wrappers for the +RSA public/private key crypto functionality of OpenSSL. + +It is being actively developed for node.js 0.8.* through 0.12.* and io.js. If you find it doesn't work for you, please file a bug (see below). + +It has been tested on Windows by [SLaks](https://github.com/SLaks). (see [additional installation requirements](#windows-install)) + +Table of Contents +----------------- +- [Simple Encrypt / Decrypt Example](#simple-encrypt--decrypt-example) +- [Building and Installing](#building-and-installing) +- [Usage](#usage) +- [Top-level Exports](#top-level-exports) +- [Public Key Methods](#public-key-methods) +- [Private Key Methods](#private-key-methods) +- [Signer Methods](#signer-methods) +- [Verifier Methods](#verifier-methods) +- [Constants](#constants) +- [Contributing](#contributing) +- [Authors](#authors) +- [License](#license) +- [Related Repos](#other-repos-that-may-be-of-interest) + + + + +Simple Encrypt / Decrypt Example +-------------------------------- + +```javascript +// openssl genrsa -out certs/server/my-server.key.pem 2048 +// openssl rsa -in certs/server/my-server.key.pem -pubout -out certs/client/my-server.pub + +'use strict'; + +var fs = require('fs') + , ursa = require('ursa') + , crt + , key + , msg + ; + +key = ursa.createPrivateKey(fs.readFileSync('./certs/server/my-server.key.pem')); +crt = ursa.createPublicKey(fs.readFileSync('./certs/client/my-server.pub')); + +console.log('Encrypt with Public'); +msg = crt.encrypt("Everything is going to be 200 OK", 'utf8', 'base64'); +console.log('encrypted', msg, '\n'); + +console.log('Decrypt with Private'); +msg = key.decrypt(msg, 'base64', 'utf8'); +console.log('decrypted', msg, '\n'); + +console.log('############################################'); +console.log('Reverse Public -> Private, Private -> Public'); +console.log('############################################\n'); + +console.log('Encrypt with Private (called public)'); +msg = key.privateEncrypt("Everything is going to be 200 OK", 'utf8', 'base64'); +console.log('encrypted', msg, '\n'); + +console.log('Decrypt with Public (called private)'); +msg = crt.publicDecrypt(msg, 'base64', 'utf8'); +console.log('decrypted', msg, '\n'); +``` + + +Building and Installing +----------------------- + +```shell +npm install ursa +``` + +Or grab the source and + +```shell +npm install +``` + +Testing +------- + +```shell +npm test +``` + +Or + +```shell +node ./test/test.js +``` + +On Windows, you'll need to install some dependencies first: + - [OpenSSL](http://slproweb.com/products/Win32OpenSSL.html) (normal, not light) +in the same bitness as your Node.js installation. + - OpenSSL must be installed in the a specific install directory (`C:\OpenSSL-Win32` or `C:\OpenSSL-Win64`) + - If you get `Error: The specified module could not be found.`, copy `libeay32.dll` from the OpenSSL bin directory to this module's bin directory, or to Windows\System32. If you don't have `libeay32.dll`, you may have to install OpenSSL v1.0.2, not v1.1.x. + - [node-gyp](https://github.com/nodejs/node-gyp) (`npm install -g node-gyp`) + - You will need [python 2.7](http://www.python.org/download/releases/2.7.3#download) and a compatible version + Visual Studio installed first. Even with that, `node-gyp` installation or use can have + issues on Windows. The `node-gyp` [README file](https://github.com/nodejs/node-gyp) has detailed instructions + if you have difficulties. [This post](https://www.robertkehoe.com/2015/03/fix-node-gyp-rebuild-error-on-windows/) + is also a good reference. + +Usage +----- + +This library aims to be convenient to use, allowing one to pass in and +get back regular string objects. However, it is also meant to be reasonably +easy to use efficiently, allowing one to pass in and get back Buffer +objects. Using Buffers is always the more efficient option. + +All methods that can deal with strings take one or more arguments indicating +the encoding to use when interpreting an argument or generating a result. +These are limited to the usual encoding names that are valid for use with +Buffers: `base64` `binary` `hex` and `utf8`. If an encoding is left undefined +and the argument is a string, then the encoding is *always* assumed to be +`utf8`. If an argument is a Buffer, then the encoding (if defined at all) +is ignored. An undefined output encoding is *always* interpreted as a request +for a Buffer result. + +The library knows how to read and output PEM format files for both +public and private keys, and it can generate new private keys (aka +keypairs). + +The usual public-encryption / private-decryption operations by default +use padding mode `RSA_PKCS1_OAEP_PADDING`, which is the recommended +mode for all new applications (as of this writing). Note that this mode +builds-in a random element into every encryption operation, making it +unnecessary to waste time or effort adding randomness in at a higher layer. +This default may be overridden to use the older mode `RSA_PKCS1_PADDING` +if needed. + +The less well-understood private-encryption / public-decryption operations +(used for building signature mechanisms) by default use padding +mode `RSA_PKCS1_PADDING`. This doesn't build in any randomness (but that's +not usually a problem for applications that use these operations). This +default may be overridden to use `RSA_NO_PADDING` if needed. + +See the doc comments and tests for the excruciating details, but here's +a quick rundown of the available top-level exports and instance methods: + +Top-Level Exports +----------------- + +### ursa.createPrivateKey(pem, password, encoding) + +Create and return a private key (aka a keypair) read in from the given +PEM-format file. If defined, the given password is used to decrypt +the PEM file. + +The encoding, if specified, applies to both other arguments. + +See "Public Key Methods" below for more details. + +### ursa.createPrivateKeyFromComponents(modulus, exponent, p, q, dp, dq, inverseQ, d) + +Create and return a private key from the given components. + +### ursa.createPublicKeyFromComponents(modulus, exponent) + +Create and return a public key from the given components. + +### ursa.assertKey(obj) + +Convenient shorthand for `assert(ursa.isKey(obj))`. + +### ursa.assertPrivateKey(obj) + +Convenient shorthand for `assert(ursa.isPrivateKey(obj))`. + +### ursa.assertPublicKey(obj) + +Convenient shorthand for `assert(ursa.isPublicKey(obj))`. + +### ursa.coerceKey(orig) + +Coerce the given key value into a key object (either public or +private), returning it. If given a private key object, this just +returns it as-is. If given a string or Buffer, it tries to parse it as +PEM. Anything else will result in an error. + +### ursa.coercePrivateKey(orig) + +Coerce the given key value into a private key object, returning it. If +given a private key object, this just returns it as-is. If given a +string or Buffer, it tries to parse it as PEM. Anything else will +result in an error. + +### ursa.coercePublicKey(orig) + +Coerce the given key value into a public key object, returning it. If +given a private key object, this just returns it as-is. If given a +string or Buffer, it tries to parse it as PEM. Anything else will +result in an error. + +### ursa.createPublicKey(pem, encoding) + +Create and return a public key read in from the given PEM-format file. +See "Public Key Methods" below for more details. + +### ursa.createSigner(algorithm) + +Create and return a signer which can sign a hash generated with the named +algorithm (such as `"sha256"` or `"md5"`). See "Signer Methods" below +for more details. + +This function is similar to `crypto.createSign()`, except this function +takes a hash algorithm name (e.g., `"sha256"`) and not a crypto+hash name +combination (e.g., `"RSA-SHA256"`). + +### ursa.createVerifier(algorithm) + +Create and return a verifier which can verify a hash generated with the +named algorithm (such as `"sha256"` or `"md5"`). See "Verifier Methods" below +for more details. + +This function is similar to `crypto.createVerify()`, except this function +takes a hash algorithm name (e.g., `"sha256"`) and not a crypto+hash name +combination (e.g., `"RSA-SHA256"`). + +### ursa.equalKeys(key1, key2) + +This returns `true` if and only if both arguments are key objects of +the same type (public or private) and their contents match. + +### ursa.generatePrivateKey(modulusBits, exponent) + +Create and return a freshly-generated private key (aka a keypair). +The first argument indicates the number of bits in the modulus (1024 +or more is generally considered secure). The second argument indicates +the exponent value, which must be odd (65537 is the typical value; 3 +and 17 are also common). Both arguments are optional and default to +2048 and 65537 (respectively). + +This method will throw if `modulusBits` is less than `512` (because +it's pretty crazy to want a key with that few bits) or if `exponent` +is even (because RSA only works for odd exponents). + +Using the command-line `openssl` tool, this operation is +equivalent to: + +```shell +openssl genrsa -out key-name.pem +``` + +for exponent 65537, or for exponent 3 with the additional option +`-3`. (That tool doesn't support other exponents.) + +### ursa.isKey(obj) + +Return `true` if the given object is a key object (public or private) that +was created by this module. Return `false` if not. + +### ursa.isPrivateKey(obj) + +Return `true` if the given object is a private key object that +was created by this module. Return `false` if not. + +### ursa.isPublicKey(obj) + +Return `true` if the given object is a public key object that +was created by this module. Return `false` if not. + +Note that, even though all the public key operations work on private +keys, this function only returns true if the given object is a +public key, per se. + +### ursa.matchingPublicKeys(key1, key2) + +This returns `true` if and only if both arguments are key objects of +some sort (either can be public or private, and they don't have to +be the same) and their public aspects match each other. + +### ursa.openSshPublicKey(key, encoding) + +This returns `publicKey` from ssh-rsa public key-string. First argument +must be a string like `ssh-rsa AAAAB3Nz.... user@localhost` or Buffer of pubKey bits. + +### ursa.sshFingerprint(sshKey, sshEncoding, outEncoding) + +Return the SSH-style public key fingerprint of the given SSH-format +public key (which was, perhaps, the result of a call to +`toPublicSsh()` on a key object). + +This is no more and no less than an MD5 hash of the given SSH-format +public key. This function doesn't actually check to see if the given +key is valid (garbage in, garbage out). + +Using the command-line `ssh-keygen` tool, this operation is +equivalent to: + +```shell +ssh-keygen -l -f key-name.sshpub +``` + +This operation is also equivalent to this: + +```shell +cat key-name.sshpub | awk '{print $2}' | base64 --decode | md5 +``` + +Public Key Methods +------------------ + +These are all the methods available on public keys. These methods are +*also* available on private keys (since private keys have all the +underlying data necessary to perform the public-side operations). + +### encrypt(buf, bufEncoding, outEncoding, padding) + +This performs the "public encrypt" operation on the given buffer. The +result is always a byte sequence that is the same size as the key +associated with the instance. (For example, if the key is 2048 bits, +then the result of this operation will be 2048 bits, aka 256 bytes.) + +The input buffer is limited to be no larger than the key size +minus 41 bytes. + +If no padding mode is specified, the default, and recommended, mode +is `ursa.RSA_PKCS1_OAEP_PADDING`. The mode +`ursa.RSA_PKCS1_PADDING` is also supported. + +### getExponent(encoding) + +Get the public exponent as an unsigned big-endian byte sequence. + +### getModulus(encoding) + +Get the public modulus as an unsigned big-endian byte sequence. + +### hashAndVerify(algorithm, buf, sig, encoding, use\_pss\_padding, salt\_len) + +This is a friendly wrapper for verifying signatures. The given buffer +is hashed using the named algorithm, and the result is verified +against the given signature. This returns `true` if the hash and +signature match and the signature was produced by the appropriate +private key. This returns `false` if the signature is a valid signature +(structurally) but doesn't match. This throws an exception in other +cases. + +The encoding, if specified, applies to both buffer-like arguments. The +algorithm must always be a string. + +If `use_pss_padding` is truthy then [RSASSA-PSS](http://tools.ietf.org/html/rfc3447#section-8.1) +padding is used when verifying the signature. `salt_len`, if specified, is +the length of the PSS salt (in bytes) or one of the following: + +- `RSA_PKCS1_SALT_LEN_HLEN` (the same as the hash length, default). +- `RSA_PKCS1_SALT_LEN_MAX` (maximum permissable value). + +### publicDecrypt(buf, bufEncoding, outEncoding) + +This performs the "public decrypt" operation on the given buffer. The +result is always a byte sequence that is no more than the size of the +key associated with the instance. (For example, if the key is 2048 +bits, then the result of this operation will be no more than 2048 +bits, aka 256 bytes.) + +If no padding mode is specified, the default, and recommended, mode +is `ursa.RSA_PKCS1_PADDING`. The mode `ursa.RSA_NO_PADDING` is also supported. + +### toPublicPem(encoding) + +This converts the public key data into a PEM-format file. + +### toPublicSsh(encoding) + +This converts the public key data into an SSH-format file. This is the +file format one finds in SSH's `authorized_keys` and `known_hosts` files. +When used in such files, the contents are base64-encoded and prefixed with +the label `ssh-rsa`. Depending on context, the line a key appears on may +also have a host name prefix (in `known_hosts`) or comment suffix +(in `authorized_keys`). + +Using the command-line `ssh-keygen` tool, this operation is equivalent to: + +```shell +ssh-keygen -y -f key-name.pem > key-name.sshpub +``` + +### toPublicSshFingerprint(encoding) + +Return the SSH-style public key fingerprint of this key. See +`ursa.sshFingerprint()`, above, for more details. + +### verify(algorithm, hash, sig, encoding) + +This performs an RSA public-verify on the given hash buffer, which +should be the result of performing the hash operation named by +the algorithm (such as `"sha256"` or `"md5"`) on some data. The +signature buffer is checked to see if it contains a private-signed +statement of the algorithm and hash. The method returns `true` if +the signature and hash match, or `false` if the signature and hash +don't match but the signature is at least a valid signature of +some sort. In any other situation, this throws an exception. + +The encoding, if specified, applies to both buffer-like arguments. The +algorithm must always be a string. + +This method is the underlying one used as part of the implementation +of the higher-level and much friendlier `ursa.createVerifier()` and +`hashAndVerify()`. + +### ununseal(ununsealer) + +This is an internal method that is used in the implementation of +`ursa.isKey()` `ursa.isPrivateKey()` `ursa.isPublicKey()` and +associated assertion functions. When called externally, it will +always return `undefined`. + +Private Key Methods +------------------- + +These are the methods available on private keys, above and beyond +what is available for public keys. + +### decrypt(buf, bufEncoding, outEncoding, padding) + +This performs the "private decrypt" operation on the given buffer. The +result is always a byte sequence that is no more than the size of the +key associated with the instance. (For example, if the key is 2048 +bits, then the result of this operation will be no more than 2048 +bits, aka 256 bytes.) + +If no padding mode is specified, the default, and recommended, mode +is `ursa.RSA_PKCS1_OAEP_PADDING`. The mode +`ursa.RSA_PKCS1_PADDING` is also supported. + +### getPrivateExponent(encoding) + +Get the private exponent as an unsigned big-endian byte sequence. The returned +exponent is not encrypted in any way, so this method should be used with caution. + +### hashAndSign(algorithm, buf, bufEncoding, outEncoding, use\_pss\_padding, salt\_len) + +This is a friendly wrapper for producing signatures. The given buffer +is hashed using the named algorithm, and the result is signed using +the private key held by this instance. The return value of this method +is the signature. + +If `use_pss_padding` is truthy then [RSASSA-PSS](http://tools.ietf.org/html/rfc3447#section-8.1) +padding is used when generating the signature. The `salt_len`, if specified, is +the length of the PSS salt (in bytes) or one of the following: + +- `RSA_PKCS1_SALT_LEN_HLEN` (the same as the hash length, default). +- `RSA_PKCS1_SALT_LEN_RECOVER` (assume `RSA_PKCS1_SALT_LEN_MAX` was used when the padding was added). + +### privateEncrypt(buf, bufEncoding, outEncoding) + +This performs the "private encrypt" operation on the given buffer. The +result is always a byte sequence that is the same size as the key +associated with the instance. (For example, if the key is 2048 bits, +then the result of this operation will be 2048 bits, aka 256 bytes.) + +The input buffer is limited to be no larger than the key size +minus 12 bytes. + +If no padding mode is specified, the default, and recommended, mode +is `ursa.RSA_PKCS1_PADDING`. The mode `ursa.RSA_NO_PADDING` is also supported. + +### sign(algorithm, hash, hashEncoding, outEncoding) + +This performs an RSA private-sign on the given hash buffer, which +should be the result of performing the hash operation named by +the algorithm (such as `"sha256"` or `"md5"`) on some data. The +result of this operation may later be passed to `verify()` on the +corresponding public key. + +This method is the underlying one used as part of the implementation +of the higher-level and much friendlier `ursa.createSigner()` and +`hashAndSign()`. + +### toPrivatePem(encoding) + +This converts the private key data into a PEM-format file. The result +is not encrypted, so it behooves the user of this method to take care +with the result if the key is sensitive from a security standpoint, +which is often the case with such things. (YMMV of course.) + + +Signer Methods +-------------- + +These are the methods available on signer objects, which are returned +by `ursa.createSigner()`. These are similar to the objects returned +from `crypto.createSign()`. + +### update(buf, bufEncoding) + +Update the hash in-progress with the given data. + +### sign(privateKey, outEncoding) + +Get the final hash of the data, and sign it using the private key. The +return value is the signature, suitable for later verification. + + +Verifier Methods +---------------- + +These are the methods available on verifier objects, which are returned +by `ursa.createVerifier()`. These are similar to the objects returned +from `crypto.createVerify()`. + +### update(buf, bufEncoding) + +Update the hash in-progress with the given data. + +### verify(publicKey, sig, sigEncoding) + +Get the final hash of the data, and verify that the given signature +both matches it and was produced by the private key corresponding to +the given public key. + +This returns `true` if the signature and hash match appropriately, +or `false` if the signature appears to be generally valid (e.g. +structurally) yet doesn't match. This throws an exception in all +other cases. + + +Constants +--------- + +Allowed padding modes for public/private encryption/decryption: + +* `ursa.RSA_PKCS1_PADDING` +* `ursa.RSA_NO_PADDING` +* `ursa.RSA_PKCS1_OAEP_PADDING` + + +Contributing +------------ + +Questions, comments, bug reports, and pull requests are all welcome. +Submit them at [the project on GitHub](https://github.com/quartzjer/ursa/). + +Bug reports that include steps-to-reproduce (including code) are the +best. Even better, make them in the form of pull requests that update +the test suite. Thanks! + + +Authors +------- + +Current (2015+) maintenance by [Jeremie Miller](https://github.com/quartzjer). + +Previous (2014) maintenance sponsored by [NodePrime](http://nodeprime.com). + +Original Author (2012): [Dan Bornstein](https://github.com/danfuzz) +([personal website](http://www.milk.com/)), supported by +[The Obvious Corporation](http://obvious.com/) (now [Medium](https://medium.com/)). + +With contribution from: + +* [C J Silverio](https://github.com/ceejbot) +* [Tyler Neylon](https://github.com/tylerneylon) + +With thanks to: + +* [node-rsa](https://github.com/chrisa/node-rsa) by Chris Andrews, + for inspiration + + +License +------- + +Updates Copyright 2014 [NodePrime, Inc.](http://nodeprime.com/). +Original Copyright 2012 [The Obvious Corporation](http://obvious.com/). + +Licensed under the Apache License, Version 2.0. +See the top-level file `[LICENSE.txt](LICENSE.txt)` and +(http://www.apache.org/licenses/LICENSE-2.0). + +Other Repos that may be of Interest: +----------------------- + +* https://github.com/mal/forsake +* https://github.com/rzcoder/node-rsa +* https://github.com/roblabla/ursa-purejs +* https://github.com/coolaj86/nodejs-self-signed-certificate-example +* https://github.com/coolaj86/node-ssl-root-cas/wiki/Painless-Self-Signed-Certificates-in-node.js +* https://github.com/coolaj86/node-ssl-root-cas +* https://github.com/coolaj86/nodejs-ssl-trusted-peer-example +* https://github.com/coolaj86/bitcrypt diff --git a/express-server/node_modules/ursa-optional/binding.gyp b/express-server/node_modules/ursa-optional/binding.gyp new file mode 100644 index 00000000..292279e1 --- /dev/null +++ b/express-server/node_modules/ursa-optional/binding.gyp @@ -0,0 +1,27 @@ +{ + "targets": [ + { + 'target_name': 'ursaNative', + 'sources': [ 'src/ursaNative.cc' ], + 'conditions': [ + [ 'OS=="win"', { + 'defines': [ + 'uint=unsigned int', + ], + 'include_dirs': [ + # use node's bundled openssl headers platforms + '<(node_root_dir)/deps/openssl/openssl/include', + "> $(depfile) +# Add extra rules as in (2). +# We remove slashes and replace spaces with new lines; +# remove blank lines; +# delete the first line and append a colon to the remaining lines. +sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\ + grep -v '^$$' |\ + sed -e 1d -e 's|$$|:|' \ + >> $(depfile) +rm $(depfile).raw +endef + +# Command definitions: +# - cmd_foo is the actual command to run; +# - quiet_cmd_foo is the brief-output summary of the command. + +quiet_cmd_cc = CC($(TOOLSET)) $@ +cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $< + +quiet_cmd_cxx = CXX($(TOOLSET)) $@ +cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< + +quiet_cmd_touch = TOUCH $@ +cmd_touch = touch $@ + +quiet_cmd_copy = COPY $@ +# send stderr to /dev/null to ignore messages when linking directories. +cmd_copy = ln -f "$<" "$@" 2>/dev/null || (rm -rf "$@" && cp -af "$<" "$@") + +quiet_cmd_alink = AR($(TOOLSET)) $@ +cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^) + +quiet_cmd_alink_thin = AR($(TOOLSET)) $@ +cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^) + +# Due to circular dependencies between libraries :(, we wrap the +# special "figure out circular dependencies" flags around the entire +# input list during linking. +quiet_cmd_link = LINK($(TOOLSET)) $@ +cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS) + +# We support two kinds of shared objects (.so): +# 1) shared_library, which is just bundling together many dependent libraries +# into a link line. +# 2) loadable_module, which is generating a module intended for dlopen(). +# +# They differ only slightly: +# In the former case, we want to package all dependent code into the .so. +# In the latter case, we want to package just the API exposed by the +# outermost module. +# This means shared_library uses --whole-archive, while loadable_module doesn't. +# (Note that --whole-archive is incompatible with the --start-group used in +# normal linking.) + +# Other shared-object link notes: +# - Set SONAME to the library filename so our binaries don't reference +# the local, absolute paths used on the link command-line. +quiet_cmd_solink = SOLINK($(TOOLSET)) $@ +cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS) + +quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ +cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS) + + +# Define an escape_quotes function to escape single quotes. +# This allows us to handle quotes properly as long as we always use +# use single quotes and escape_quotes. +escape_quotes = $(subst ','\'',$(1)) +# This comment is here just to include a ' to unconfuse syntax highlighting. +# Define an escape_vars function to escape '$' variable syntax. +# This allows us to read/write command lines with shell variables (e.g. +# $LD_LIBRARY_PATH), without triggering make substitution. +escape_vars = $(subst $$,$$$$,$(1)) +# Helper that expands to a shell command to echo a string exactly as it is in +# make. This uses printf instead of echo because printf's behaviour with respect +# to escape sequences is more portable than echo's across different shells +# (e.g., dash, bash). +exact_echo = printf '%s\n' '$(call escape_quotes,$(1))' + +# Helper to compare the command we're about to run against the command +# we logged the last time we ran the command. Produces an empty +# string (false) when the commands match. +# Tricky point: Make has no string-equality test function. +# The kernel uses the following, but it seems like it would have false +# positives, where one string reordered its arguments. +# arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \ +# $(filter-out $(cmd_$@), $(cmd_$(1)))) +# We instead substitute each for the empty string into the other, and +# say they're equal if both substitutions produce the empty string. +# .d files contain ? instead of spaces, take that into account. +command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\ + $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1)))) + +# Helper that is non-empty when a prerequisite changes. +# Normally make does this implicitly, but we force rules to always run +# so we can check their command lines. +# $? -- new prerequisites +# $| -- order-only dependencies +prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?)) + +# Helper that executes all postbuilds until one fails. +define do_postbuilds + @E=0;\ + for p in $(POSTBUILDS); do\ + eval $$p;\ + E=$$?;\ + if [ $$E -ne 0 ]; then\ + break;\ + fi;\ + done;\ + if [ $$E -ne 0 ]; then\ + rm -rf "$@";\ + exit $$E;\ + fi +endef + +# do_cmd: run a command via the above cmd_foo names, if necessary. +# Should always run for a given target to handle command-line changes. +# Second argument, if non-zero, makes it do asm/C/C++ dependency munging. +# Third argument, if non-zero, makes it do POSTBUILDS processing. +# Note: We intentionally do NOT call dirx for depfile, since it contains ? for +# spaces already and dirx strips the ? characters. +define do_cmd +$(if $(or $(command_changed),$(prereq_changed)), + @$(call exact_echo, $($(quiet)cmd_$(1))) + @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))" + $(if $(findstring flock,$(word 1,$(cmd_$1))), + @$(cmd_$(1)) + @echo " $(quiet_cmd_$(1)): Finished", + @$(cmd_$(1)) + ) + @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile) + @$(if $(2),$(fixup_dep)) + $(if $(and $(3), $(POSTBUILDS)), + $(call do_postbuilds) + ) +) +endef + +# Declare the "all" target first so it is the default, +# even though we don't have the deps yet. +.PHONY: all +all: + +# make looks for ways to re-generate included makefiles, but in our case, we +# don't have a direct way. Explicitly telling make that it has nothing to do +# for them makes it go faster. +%.d: ; + +# Use FORCE_DO_CMD to force a target to run. Should be coupled with +# do_cmd. +.PHONY: FORCE_DO_CMD +FORCE_DO_CMD: + +TOOLSET := target +# Suffix rules, putting all outputs into $(obj). +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD + @$(call do_cmd,cc,1) + +# Try building from generated source, too. +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD + @$(call do_cmd,cc,1) + +$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD + @$(call do_cmd,cxx,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD + @$(call do_cmd,cc,1) +$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD + @$(call do_cmd,cc,1) + + +ifeq ($(strip $(foreach prefix,$(NO_LOAD),\ + $(findstring $(join ^,$(prefix)),\ + $(join ^,ursaNative.target.mk)))),) + include ursaNative.target.mk +endif + +quiet_cmd_regen_makefile = ACTION Regenerating $@ +cmd_regen_makefile = cd $(srcdir); /usr/share/node-gyp/gyp/gyp_main.py -fmake --ignore-environment "--toplevel-dir=." -I/nodeapps/https-test/greenlock-express.js/node_modules/ursa-optional/build/config.gypi -I/usr/share/node-gyp/addon.gypi -I/usr/include/nodejs/common.gypi "--depth=." "-Goutput_dir=." "--generator-output=build" "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/usr/include/nodejs" "-Dnode_gyp_dir=/usr/share/node-gyp" "-Dnode_lib_file=/usr/include/nodejs/<(target_arch)/node.lib" "-Dmodule_root_dir=/nodeapps/https-test/greenlock-express.js/node_modules/ursa-optional" "-Dnode_engine=v8" binding.gyp +Makefile: $(srcdir)/../../../../../usr/include/nodejs/common.gypi $(srcdir)/build/config.gypi $(srcdir)/binding.gyp $(srcdir)/../../../../../usr/share/node-gyp/addon.gypi + $(call do_cmd,regen_makefile) + +# "all" is a concatenation of the "all" targets from all the included +# sub-makefiles. This is just here to clarify. +all: + +# Add in dependency-tracking rules. $(all_deps) is the list of every single +# target in our tree. Only consider the ones with .d (dependency) info: +d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d)) +ifneq ($(d_files),) + include $(d_files) +endif diff --git a/express-server/node_modules/ursa-optional/build/Release/.deps/Release/obj.target/ursaNative.node.d b/express-server/node_modules/ursa-optional/build/Release/.deps/Release/obj.target/ursaNative.node.d new file mode 100644 index 00000000..fdc401c8 --- /dev/null +++ b/express-server/node_modules/ursa-optional/build/Release/.deps/Release/obj.target/ursaNative.node.d @@ -0,0 +1 @@ +cmd_Release/obj.target/ursaNative.node := g++ -shared -pthread -rdynamic -m64 -Wl,-soname=ursaNative.node -o Release/obj.target/ursaNative.node -Wl,--start-group Release/obj.target/ursaNative/src/ursaNative.o -Wl,--end-group diff --git a/express-server/node_modules/ursa-optional/build/Release/.deps/Release/obj.target/ursaNative/src/ursaNative.o.d b/express-server/node_modules/ursa-optional/build/Release/.deps/Release/obj.target/ursaNative/src/ursaNative.o.d new file mode 100644 index 00000000..d80fdcca --- /dev/null +++ b/express-server/node_modules/ursa-optional/build/Release/.deps/Release/obj.target/ursaNative/src/ursaNative.o.d @@ -0,0 +1,53 @@ +cmd_Release/obj.target/ursaNative/src/ursaNative.o := g++ '-DNODE_GYP_MODULE_NAME=ursaNative' '-DUSING_UV_SHARED=1' '-DUSING_V8_SHARED=1' '-DV8_DEPRECATION_WARNINGS=1' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DBUILDING_NODE_EXTENSION' -I/usr/include/nodejs/include/node -I/usr/include/nodejs/src -I/usr/include/nodejs/deps/uv/include -I/usr/include/nodejs/deps/v8/include -I/usr/include/nodejs/deps/openssl/openssl/include -I../../nan -fPIC -pthread -Wall -Wextra -Wno-unused-parameter -m64 -O3 -fno-omit-frame-pointer -fno-rtti -fno-exceptions -std=gnu++0x -MMD -MF ./Release/.deps/Release/obj.target/ursaNative/src/ursaNative.o.d.raw -c -o Release/obj.target/ursaNative/src/ursaNative.o ../src/ursaNative.cc +Release/obj.target/ursaNative/src/ursaNative.o: ../src/ursaNative.cc \ + ../src/ursaNative.h /usr/include/nodejs/src/node.h \ + /usr/include/nodejs/deps/v8/include/v8.h \ + /usr/include/nodejs/deps/v8/include/v8-version.h \ + /usr/include/nodejs/deps/v8/include/v8config.h \ + /usr/include/nodejs/src/node_version.h ../../nan/nan.h \ + /usr/include/nodejs/src/node_version.h \ + /usr/include/nodejs/deps/uv/include/uv.h \ + /usr/include/nodejs/deps/uv/include/uv-errno.h \ + /usr/include/nodejs/deps/uv/include/uv-version.h \ + /usr/include/nodejs/deps/uv/include/uv-unix.h \ + /usr/include/nodejs/deps/uv/include/uv-threadpool.h \ + /usr/include/nodejs/deps/uv/include/uv-linux.h \ + /usr/include/nodejs/src/node_buffer.h /usr/include/nodejs/src/node.h \ + /usr/include/nodejs/src/node_object_wrap.h ../../nan/nan_callbacks.h \ + ../../nan/nan_callbacks_12_inl.h ../../nan/nan_maybe_43_inl.h \ + ../../nan/nan_converters.h ../../nan/nan_converters_43_inl.h \ + ../../nan/nan_new.h ../../nan/nan_implementation_12_inl.h \ + ../../nan/nan_persistent_12_inl.h ../../nan/nan_weak.h \ + ../../nan/nan_object_wrap.h ../../nan/nan_private.h \ + ../../nan/nan_typedarray_contents.h ../../nan/nan_json.h +../src/ursaNative.cc: +../src/ursaNative.h: +/usr/include/nodejs/src/node.h: +/usr/include/nodejs/deps/v8/include/v8.h: +/usr/include/nodejs/deps/v8/include/v8-version.h: +/usr/include/nodejs/deps/v8/include/v8config.h: +/usr/include/nodejs/src/node_version.h: +../../nan/nan.h: +/usr/include/nodejs/src/node_version.h: +/usr/include/nodejs/deps/uv/include/uv.h: +/usr/include/nodejs/deps/uv/include/uv-errno.h: +/usr/include/nodejs/deps/uv/include/uv-version.h: +/usr/include/nodejs/deps/uv/include/uv-unix.h: +/usr/include/nodejs/deps/uv/include/uv-threadpool.h: +/usr/include/nodejs/deps/uv/include/uv-linux.h: +/usr/include/nodejs/src/node_buffer.h: +/usr/include/nodejs/src/node.h: +/usr/include/nodejs/src/node_object_wrap.h: +../../nan/nan_callbacks.h: +../../nan/nan_callbacks_12_inl.h: +../../nan/nan_maybe_43_inl.h: +../../nan/nan_converters.h: +../../nan/nan_converters_43_inl.h: +../../nan/nan_new.h: +../../nan/nan_implementation_12_inl.h: +../../nan/nan_persistent_12_inl.h: +../../nan/nan_weak.h: +../../nan/nan_object_wrap.h: +../../nan/nan_private.h: +../../nan/nan_typedarray_contents.h: +../../nan/nan_json.h: diff --git a/express-server/node_modules/ursa-optional/build/Release/.deps/Release/ursaNative.node.d b/express-server/node_modules/ursa-optional/build/Release/.deps/Release/ursaNative.node.d new file mode 100644 index 00000000..e567f0ef --- /dev/null +++ b/express-server/node_modules/ursa-optional/build/Release/.deps/Release/ursaNative.node.d @@ -0,0 +1 @@ +cmd_Release/ursaNative.node := ln -f "Release/obj.target/ursaNative.node" "Release/ursaNative.node" 2>/dev/null || (rm -rf "Release/ursaNative.node" && cp -af "Release/obj.target/ursaNative.node" "Release/ursaNative.node") diff --git a/express-server/node_modules/ursa-optional/build/Release/obj.target/ursaNative.node b/express-server/node_modules/ursa-optional/build/Release/obj.target/ursaNative.node new file mode 100644 index 0000000000000000000000000000000000000000..0e9e18ae905d9d44cc4eb3b86473c4f706013d90 GIT binary patch literal 73184 zcmd44d0>=9@;*M?5rv70ii$ESDxzW%2$v!W5HgVjBH>cR5R!pJLK2e+1VxM{QO0p3 zx~O>LjjpbE;~fw=JXV(Vz||G-Sb9VatGj|1^Lw7^erI|@#`UxN{o^+p-mdEE>guPe ztNZQuo#e`_+;JT{bZ|MJPOfuZq%y{6PKK#id1Oo`!!^v+&6VLg&eca`yBL}FE-OCL zT<7X?d4xf2UGcN>6CrW+NWr;!x@mrjxjOASg3WfGzw3I>-#t=ru6vA`&NWGkxjN&@ zpG~H|?X{ngbFP%-C;v--3Cnxl7V>~=FB*i8b9LICk9M^4_kNO%;3U&uB3x#5(t^&_ z3`fS+3stPno-oDL`PuUONA=oT_;hB0`60J5F1g^!LN+Wn81La^-h)d0a^u-2qH5m*>!oeq9?5JK@Afk{|5+ zdjGzi#r4$3PceRc_?e5JGW_r}4?pGjnU9|;{9KBkYW&pVX90frS%{xS__+)}m*eLO z{4BxGmH2T!SD|njeqT~Q~-;du8JNlFFy7b(&qSL1bHJtF#_{=Y!RIa>brB4=ZJ%8|y zx>v&sZaX4l+gnp!Tm0IwmrQ@?yPf@>J%8%awQt-u^|-4Ke*de#w)Wio+R87!|7h@z zK>7MRMpXA2e%rp*>K8))?0Msit0(>QYggV=UkuK^^5xU=Rt)+2?Zc-I-tpBPV~>1r z&_6qj>iN$r7T0gvkUDPQ(6mnn?>PCSD*_kq8&$dHjD@Y6tJdG~War%EgD(2h&d+M| z7yYrcudy&U!Qy1(EI=V;c?4Cf4<<6YX+7bQTy58 z9WQ-;)8cy{JoVpGmTzBN*O0eo+ojX{EJrYBE_B1B2^Wp^K<$U+pfSGaz z>^ZC*{#gm|IT-W1J^AtkW#QzJ4?1#@i?fCulp6%Ot%MtDKT^MhB@!2=Q zcuNz+TX~Q6^$bg3rz?T{lmzj1Ujp1FLH~*E;BZ+2+)@+h&q)vu5$J9YpG^tm^Ap(l zdV>5=k|2K0OyIAz3HrS~!FV6Vg5RF~=O>tVT@%=!mLNV)Mq+AD|EdJ`j7VVrQ^-s0 z=^1oL`}~&@#HTxf{ILn*d@1a2FE33_U}tp#zsyU}?@YDxe4Td zO3-h80^EL15TCUPaJVeNI(2h`eh*5Z=avNV|7(KrmIMFx{Pj$NcwUyE-wzY?+ZFb= zr@t(Lp2HHv`H%$hd|iV1m4*AA!(4~B>L==CcD%`Hw_vkQepP{H6dQhj%xm&n^5glp zAs$WyKYyL(&oJ`)jsBHJ-qAnK=%2+ziqBX2;yM-hh@SPD!Tmcw-4Q43*TYRRK1X8w z{Cwdy_M6Rn5^&__0pKR`k7)WCeQ}+O_#wa9D1H`r@so{tL4NXNO<#JPzP>E`2lP8Z z(;owZX?+TvxzO;}#O;f~i=UUwcvs)7=~m#v&lg6| zN(0Qhn(Zoc^t`GW7aRFQ4L{>W&A-dcm-(n?zxf9LTa2Fb&AiLFUo$>H9P?9+co4ss zdHR56yC#}=NHOtXrjhIK#_w(YxZB8YX%j!^yR|(nbz1RrW+L5c^whtu`D0DLt+4Y@ zY$`W>?hy{u%I78HuN}r;P%EEZCZ1QDd3~$lZ#`7^yOKBQ_|zGE&M^2lH)wtsc=1yv z>-$lz7Spfhx?IPaep5_-bLP=v6L0y~Ye^^G?l9xsbA#qTh;j1M!|+#{#N)_w-nZwk z#bQry*OoT++-$~Gf34QL!HnxktasG2@-fZ-(eU3haqG(0diW4V_R~F{ZL=5tYXzCs!Ah`D=0t(h9S(vc{%mE%<+_E>)|8Ekh>GzQkAT zPfIB%uUwez^XF7xxUhd*nXkMg3qV{rVLVOFs?+@RsYT_rzG(B*RBus5Nx83}xU$NZ znl`4|SLF9;R#yImg2G{CMqg@**H=`fJ7Z01q3JmbZh!}h=M@&0&MTZ#R94PD2Uk>< z_)=4}{Iu$#s?@Y;zM^?!iptApLpE#DcmkO^#AfDH%&E*NNC95dfabnROJ)f4;cNRN%4ITA5-ots{W16+r`jC(d4NI!rOkgV@;eKV9(eTL87EQ zU&31d78R5m(iVqvkrTAUBp4b7>kEJrA%rXVKA z)K*tx?r8AEmLa2S=gjd{51Qaxh+wkhv*t%fZe#|JE%Fy-Q6@dNvbd-`$BsRO%6#Aa z;;Kc`{{qKS6FX^>E2T-+{3`#VsO#fGeoU%_xnr&qc|!{P)nyfPQ&VB!xa!LJQ~Yy= z#S7+-FQ)%F0xc`fm-&X?hiBCl`>L2C(zB|oE2|kRQS%Fpc7%`#bf^2&!IMj?D;Gu^ z$2T)mH`*$0AdXXPcqvemQ-Rr8QSAE-2%Y(A5Fe83tC;IA{f!2rClt;ut4Nz&;X8^EUR#3O`23V*XJ+vaqL1#33-C33Zs}4zz7sxIDE3N&Ofb%1VqghD@lPKRX(m1%-}tvP3{H2-;2JSp)(arlxVG)cE`NLpSzXh9D=Hrz6)i@Nt17B4nx8j$jKI4^T(&Auo-E%vW>BE;?$fUCmpXEUf1#N z_L04%pPWzo%O>}qhE#f-_IH_a37UbzArR@yDxQC)qz>Q>_J`+_@l>&GB zDv3)}ALZK9N1;Kw)53B|Hb#ugN9xe5sriLta`L@dlM2U7o?ckC0Qd~`EvPCiE~_f_ zRb!p0!(bqqmVSU}VMS$eB~o5~do8#rDV$$fQd{mTbT)uc6J6Pc=U@jprW|{T_~e%o z-Rwk@Z(2%LO>t2b_k7k4D#3D+I#_RnCi~`BaaA?#DK|Kn-^ozac%ff(z(4i^mVjnpA+q01_Z^TPoP?g4&jrxUYhOtgRj zOlSSFR`-Iz*!508vcc}AaCiY0jUs<-wGVEmMXAGqI@ZowE)%1Dr9}(Mu%&Q7Jiw^b zG>l84ctX*9toyeA4%m7e7;C9R9M?yqPd14FE@s(*1CQ(GK&>W%9q*;B^5I(tF8+7mza0|$1y~e01v-`;(yk~J$D|nTy4#NZO@RH zJ#bCFZ~lL+DV>^XXP1{1|Bs3W8+^w4imMk@{r6Bida^41H$8*&sQy=TjGF(|8YZ*Y zT>76JMos?@95$GF?7t10Aya+TWpn<|Il-AvgHrTSMhp?&#*L|*uczsMJulLR8@&!b z|8LZ$4w+cxtI(hq)Rg`g$Y&V$lKg^#{GyT)+-v=}@TVI5|9egCXJ_V0XLA$1 zBRA{ufmu1aR2B>>bjh|(uYqRig>p0lC63v{;?5fNw$s@uI4-h7%HofphWqNOaGuEpI=_Ior_s%M>JVKOo6?R%%%(xZ%rR(u zpB!DDehjuuNE2d()^9Ow|D|gGO{u6c&gJ0|aHmRML87K`VP$oR@aCEwB2QEb zeRYnX=(EDvwQ~dyoL85$<1V_=u5yqnlmmWjH|y}EpuB8$jlZP$^wS5{R1O?MvdUk| zR-{u%7weirUkT12an3!vrUo~jc-r79^i`C&YH`Xlp~zphz&DV0magpFoY7+n(*~vv zjuvC3w1MfGJAHcLpn-$+ql|?A^3jcXJQP=AgBYJw>|^uoa!ev|$vm=2EPxvGILYNa zesQ@v{Qu@Z8r}iO6w0$DybBI``Hi>W30)W0jfU5&tPD@8I=k*PbnP)^c*54n^$=)& zIGPMoN7{edO?V>J(e;$6ci!`Mo(s+zODUIYm3jW{@SXS2SGVEM8l&acwBdV}I3 zo1@2}o7?cGZ`OKNwc*b<{4GX5A44zEqVn%Hi(hK-cUb)87C+g%r%pXKUs>{tE&1M- zyv=u6eDerWS|wThD=a<9+dV?@aqUuz-`nC}ZSg%8|2~V~-{PA`^HQ5)@$o1%`Wa^N zeNirA$>N(w=Thsn`28&Te2X8n_|q+ZmBpWB@tt=!SY2xI&$8sJEWZ7|d7Z_-*OITd z_+=Jgo3Qvu+|f_H#jlQXkt-}dUU`Uqnk_zF!H9lV zSbV%<5dEyQ_}4|b$nzE-ufRk<`#!iov$Ui|!`XBF3j}*v1QA+xs{GA>tkbjbt^gq*gdZa-9$x_n) z%-ZRZ0{N#%N&i#2(<24)PnDAXr)sB13gq{flK!V|r$-9ppC%>!PyJ4h6v%hp2_j?Z zP7g0K-ZP}6|7qUokpkt2u#ZHeD$R8*r{m;ss9x0GtCnf#Qs+}GwkiSey`k&Q1 zJyIY)MN0agH9I|0AU{<~`k$7a9x0HYCMEsPrkx%skY6Ju{m+)29x0GNNJ{#jZ96?u zAb+rw^glaxdZa*px|H-kYNtmE`7_~sQssoi1m z3oLnM@h4mSJr;k8#ouS~r&@fM+0QWkr&;_Yi$C4sCtLgrEPii`f1$42bVt(MnuR?=|AZlz_8^@s^mn9tl6DFG6=^r=J^R5p`7_eodWClg{WsFwa)q}D zy_Gb#RN)q(-z3c~Q+Tz|>qv8}6kaLxi=??l3O5V=6lrda!u3KwO8O|$RYKoKnp>Xm zETL~F&8<#2U+9}ibBhzs5c)dO+}eawgua?Iw=`jo(3g?smL;4lbTw&iRl+WzFCpER z^qyZi{@J8Gq<08?A!%+s!drx%MEXS1Ekd71`Xth;g&s|sx0vCTLXRNLEl0Rn=rq#Y zYJ}^B9zgn3(p5sANSa%V@GPN^AC;K42;Gr1w-jNI&_CS^ znp=r*ve4g=<`yFC68bCBXOZ6Xi};^3w+7)ILjR34w*=uWLT@F_tw6X%=r>7osSmFf zdL3yl@!^$1zet)(d$?KXr$}>257!I*DCwc3tAxIfG?(!3ETL~F&80h>FZ4~Mxnzek zguae6m+Eke&{vb@5*_vkeHm#kwc%u;t4VW-4ZDQCg!CxVdwv%Glg=Q$L+A@hb14mP z5qc8o(WG01K9BSm(yN6YO`1z)c%{%INOP$SHw&FcnoDH3Ug!a&vq@J8eIjWtiQ!p7 zA48f;VK`st!$@-p3}*=4oivxeaEj0!Npr~ydxZXJC1@^n;bft|Bh4i)>=ODb(i2JV z`APgwnoC-EhtPi`&7~~7Md+=hxrBvVgnpAWm#*+?q1Tb-k`-Pl^oyjqRE3*`eu^}g zsBpc|kCL87x=QH#NOMUF&l37}(p-wd`9j}BnoCePL+I;BbLk1E2z@naE;(V3(3g?s zQWH)Vx|%eXn6OLeOGp=z-t(jQpY$x!JA}TFbP?$-LQf(+n{H0f8t~t%1pE&0&M)1VIWT~46d;rk%#KN?Hp z?QDmovB%8Fj+p$+*SRXjXqXdbKcV!`aGBygZ9n^3yT6k+u*bVrjq-Nb;Qh;fe{U!( zG71l&LdV{=`szpC20gCYv%C!>hoS*g!k$AgjuXLG-ylURFWj=B%cY<@uz5X(<@)}0 zs00!epBbJ5i5Q(ZHFHYlVGo^Y1S=&-ua)OKddGbQ#{XE`a zcEtT$#=&R4gvy3}9TwER+5x59K&vVSY~H{|bvBZOG{^~TI6(Y@)E_82RAjSOdjm7q zctcmTeD7Y8wZ?s9)@t`@SuL5754^#wZ6)48+J@Re*mJ=* z*Y4|NT%eCquYrcit9L)72BSz%aJ*(@+|QhRJABd5lI#t1^9HX>@is;LU6evxqwbO0 zP#3&BS?ZghsFOd{{ap6J4LiCus7~i}SU5o4K*K45c1LhSGz0O1o-BV0^L1~i$9GM@ zFO>erD|s1tbiK>4L9m(inbWj~asvAc;32Q=o=vGO z-liYijosh}Z{T}xC~sBj)>k{BBPday{t$_bgs(^C1lGH+Jq9xBSeQFD@DIAGY9G35 zYRL(_;h&xxykZr3xv0(!e1>9fV85CGih8EPl$>DKoZu871kL$~*Q`xZ7rC2WWQPsw zy~a(Mg)>dO<%WE#)h>)n-3RP)1G~I|4XPU^uDS^{x>nZ_(@^?Jz$ta>3our~Xt}nn z)(wBIP!EZRvR2G#rj5fyQ!6zchXF#VdY=L?^l{KI)En%r(x|s#-wJ;(Z!n|O8yM3& zoDJn>K6ry;5Cq^20#9{i^H7h%2Kp*}=@MQ>hOdIl3IL@#3R+D&@key7*q%_SE$UqK z+1TPAK~p-i|G;)2ua5e6B$B!{uz{BT3@E+9JO%I$kvUeoz{EFW8~x7Qq894WaDbmc zT+IbdJ%wUs`oXZzf~t%fk%;;dn?4XRD0e`wG~@-Ko!YYdIv}}8T?B%@+r3pCilUA$ zJ^yn8zj_0Ea{~Wj7O+Q#6rk4sD-sD!@7d7O&7HGt?a!UA!ssHS+}EDXnA!+Uflt{z z{Q+CNf!E!QJ53P&h+1RP-7u-CrEWw{Fblc!W5klX@lA>a4>v&-oA>Uf{W_@Zxlepr z)Le`>^#}I%ca)H5)R$1KGB~!tcEa``>`*D730r?$4PLncX*NWg>A#dZ!U#2E-=DwN zkX-|o*oZj#ijl}T8XS$I$+0+62ctTC1QdV~3htNh+_b3uPPamJeq(t)fs>O*=g zn6+kiJ%aA5dI`G27faCjF%5Lk-3MFLd`O~IEWgC(gI@}OM>G62-S!u9f*MS#H5Ru4 zo19?hez2@*tNRAxof|AolJN!BHGI~|+wfC|+MXC)q`vN8mpi}%``pm{)v6V}BVQBH z$pm=2L0jw(r9XUmTpaF1h`{&m##QtifNhrMd)d79JJF=hqz2fM8}z6fQ6{kN#);^V z;N}Fz_Up}%?aHe740Coz$TX~!y%ZpG(0ZqM=n$K|Af)Sdon{)J9vwK3QSq5mS7l?F*gRMEOj@IgWWkD zHe{u?q;AgK(6tUDWxG;HW!9hTayP9d)`5unU=N2M$wayf!mU|N-_$M;%kP3MI+72k zmjK$abo&ArWPtye^c>I}(8ah$BN;o1jj9~g1idMUl|MW%YJW~}Y`nxL?g4M8L5}yHqxXU?-L?{K#n3Ncp0Oy07QH9tZcuOI3W#4^M2Mm6 z1z3RbYMem({VE_$B@8MAhgNlpup)wI_-pLaq>p;xiW|R#0#yZ?qb|i2eRPmMqyvt; zTKC~@x)JTegJGzQIXngih*vM=h=Nxv4PQo+P6CCQ6hD97=hgrjFDLLWCJ{CWS9-X# zU*>JNyuZso1}kgrggiKFS`@#$rbwpjdHg-F5lB(LKy7Z|@)R!HV*`7v=+yZj3*K$o z>fZrX{v*)8dJ7GpGB;4{@jsOtEbh-m;W^PVumA3qBL9PbwOCO57qqQ?d-r{9=D*pk ziQ(@X!-vuE3(zdX(^+(vBm@1~jWb6yEv zFml-LHL|~wZHE6X(O>%+&HDT9R~$Ue{xO*CMJU#Gp^{2(!zk4mG-dQ-y7)YZQ3m56mI|&V#O)DUu&}-YJXtM*Ud5~Nz8#Hy7Z5y)5pookItO;8GbV5N2&g;Oca+V zslF)W22O%CNisWRp3o*v5qVzY&A zHgZEUKwAbJpxHxhR1bi}4u`6K3_G%Ff^J4NHDA-85qIMyFaoDA zf4t5k=LYk@mxk*kDX6nSV-zJo8T+c-z)zVkF#V@)=FaK{5te(%?{$%PkiDfSCkuIE zMyq-dEYZi+rF0k9f0_~sF=k+-7YlwM#Dfxb8JegrsLc(0OX;7){HA=?ed~0B1{+ir zYKYNZbqdv67FnS-Ln(g@j-HaGbgs%jnyN?l!+yP>=S7n25 zV{{aK8Vu1yKs6kWw4q`PpR^F5-qb~Iq*^)DW7uCPeLz)QnDnEm43mxSMs+lIt*y!h zN#gz;VBu*%GmOTS`oCl`_$&b=ITd}VwbGI7^G<;_^`y{(=|eJH9XPi~?IEUpP@^&3 z3gc`{pZXFy=0iA&skme}pa!Ngc0hIp4bgFT6>Ib@&j-+jA~F3LrU<4dVpNE`f~6YM z?;U5DxO<%d1VeI95K8|NLvM@ep-^h>6BpEVhvOt;V=gXuH9HKvb2 z(#G^0$QVp-WHE+mM@Xvq(ve`g71e5{(1PhCYB!T{oUk#MB~CZ}!@+b3jI%Ml_zUPb z8p83I-iihmrrSUoOwVME#`J0eq%nOMpbMs5F)CnMc#X#N9>*C5(@M}WOmBoQ+hY2P zw2(MG5&8iyG0g^7RkOcP`n~hxFkMW845llN(wI(%q>ZUU%^$gceNqqosrCciJ?AsUI~uPMHsFOuK&$9dCdckLehyip6Q8*aVpk>LWP8U^-AY zW1JSior39dJnI9dPd8~y$1^Gz;0DuU>Go)xj)X7UVp=9G1k*q3A~F4*Lp`4Th0S_1wQZY7c?% zphjc*0gSUTeQqaoTngcMOj`l9g=vb|B$zg_M#t&jpbJG}8i6T-X&s)Y0@Lh9jp<&; z83xmh1R#oO7(;K1=@C$B=Kf{6NKEhHP~T*Kq4cBX#bNp$4KkSaM(@OQH6(3JGazFy zy_v-rrd=VaE|rc1(+^Osii8$Sr&7C_`{xPUnfq^l=3sg?jI%MFy#qRqgK#{icc6iV z=_eq~+)rhV#`GEjq%r*?Ko?Ah;h8ls9n_#Pz29+$!L$Z+4AYz8%eI)Vl@=1Gr$E1% z`{Th?3)o*M{k^g{OzUZo!E_s*pcB)JAZcUzH6q7gn#rNWFnx-OkCToB)2mUfdI&9; zc9h}jIQ>DJX6Ak!bm}-A2)>PJ&+X8$8O(T0v(do9bg9?`nGNdiaDu@!O*dnlPJ=rI z(|veP0GQr-mBw@;qr#f|ed+dSoMyt8Z84oMEd^K~oK; zccFJ;ngmH3(-knK9^`#IDaKYhav>>6}lX;{*uD zV|ou7SeWhrY36=9Yc!_U5g>1#_grVl&LFqkd`9mDiC__8ggZ%7M? z(*e*gb07O(aMfk(FO=RDk9;jm8)=ZibRv2urn4YvW4Z^CV=&F)P-2)qN5v;dM}p}! zs8)vxEtqzd;p#a3NtlnLG6SS45mYL zGse*jxKl8#bPJ|$U7;~8U{qLh|0KFS8mC$CWm`-yl@@~O2f9f8KXa(3u)k1xO9`IZ zZpH~R?{m^==rY#mDE&e_C^P>c6a~?PFe=Radlzd& zJAiK^`WNw(v*Z6BLvM>{UuhwTGX6}IKEk2C2O5Yj#)}M5M0d~}gJ?q!jp)mevk}dO zj6w8X7GsDW21#{=bR&p3u+amgov=BrY ze+JQM;HsVy4ap;?~{u0R9i2j7AF^Ep&Kw^ltQ0?i`jUd{LYIUs8 zf@rb~R>x>(VLOOk1D!fX&w&mb(LNtS$A@6XBRT~QEJSY+n;^46?S=~sq8YjwXQdC$ z1fsQF)LV3GFn#eN4e3Q7?I1lvs+}O609Uq!^fGB7kZ#vScF-9`brw4erSF?%L3%bV z6-d$f1ZmK!j)b6%=|eEuVEQwQF-*&;_d{tWn4SZ5YNODC>B}-)jp=G(JD8@SMq|o& zvoYQDK6ErdI3CjuR292}8cjp=o&K$Gg2D7_@uAH7Ls8V2E+jLUURS3vO#*3Sx=ozr zVEPlr-WJnSq=jG_)J0;tnq&Q#xqCF0#Iv!iqItbdBPJ)oZ^kEibnD&OG zYLI>eQ-x|(BeY;zO7&*uUnFb?(@#HeFkKGYY)t*{LC0ATj>q(IG_WxJ7No&+3~Thv zUqO8I%zp)-YfMiP(9*wNpfP>M@rIfDjp8f^(}&>9wwP{}7J}(e=rU9PB5>8U)E!D+ zWyk3sXpe)bj>lG20YMwn{fHccX#s~4!*o6Mo+bSVrpr;S`U)+W_LAZ1I873^gXwk9 zspB*QI&4fme}#^Z!HmcB0yMBNyC=krsmK=eo!al2BBG*kLF=X{HsYqiCsvsgB21bqoY;Odo~O2GavSs#`F_$mV@bjjJ++U1Ehsux=a^|=`$Sb zcIpnLZ=GRbx|{YmnCf_JRU05^V>%T=2Gc*X7{jy=B-ORjk6`*Ws?|cF1=Dh>H*KxjzeB6{PM^`mzfxOmC$<4yHODTU9j#ZA?3g z{c;C2jl~$Io2Yk?^dp$AK(#taXu-5M)f-F?5w?Tr4Twe^r(>bR#DAIgFx{n# z?BEa-)lhbbCqWljn2w>P4yHODTh;Lpv@!h?j5cxFNk;aHHv)YNMSrWh=g<0uj1NIW z|8~5E9NqkW&hb+JM(itoAi_a;N`=PUw0S#jg+n{RRf#Cybs6;c< z@oESIW3^AN5*m3Z8ZX@^QGsl-L2ZPweEQi%ohbuJKNn`QlUGq;9xJWma}UM~fOsA- z!aaBiNS;;6kXzMG8L~KN9MmA_@midk$0m5isQ~uz<+LDs2&MnY#`0ELC2!Hegh$!H z!4fZKeyaKt>iD;#{tCFfSFPvMLF*M1JgJuc!q?+iLqA_sGoUWK7q{ew9#6U_j*<+0 zHtF|b^y#EWXUz|w3SmdpDghm)F)<1^Ea@e}9S*rOCrP(Zf^G}qfv($s72`pW^2c@wrJq&&F^x1yCZ$BSa@4N-* z`CN3pdI}DN<05!fKl(}*!%_vH>N|IGmmiVR5KZvA`T$X%xuy%96j&?afkd=jZGV%m zi@FpQ{UoD(ywUzNXoJiOt^K$Iv{xGKdy$w7GB0DC?I82UW{u3R0@-#oC8m9Z*8U;B zG7*pap+@_?G3^((uYIo3{)ExK7qqec6M}?O(gU&o5{oB55@E*pF zjL5V)9FV;>464+2Fb$5+Y(jeDi`digD$VOjISq^Z;k}ZkUDEe<^(?H$TZ=cW0nPUx zx8t32l>v~{<SjJbP`A$*>y2bnA**XU3jK|=9 zHI#@UMV&={DE-s(qf-UmQNtPS&imqDV<56JZBT#N06w4#fQ9$P19*vYlRAR~1u}SF zd?(za-xrS>+u8Y+2w#3b-{|#tgLNt1khg#8R=O5Sb|Dz3#M@AZ*D5idnSA}dkAD5V zo$)MWr+Pp737V?8pgEpG@+!PsV*M-tI=l zWk;!x-wT7F zx>Co|-cXPAy87?B`dNl@Dyx545C3e0+E_eCzpsM)(QLkZQ`$CvEQe(#fBZ;41v}xD zaJ=v3Zp_8^uxR^DP)bOT1DzA>)$c$|hvB;!g6Xv|0ug{E#ohP;t$OZt8K=5igN;<; zZoCQa>!6!pRWjZkTlNdYQn%tQN9^199$-#zK}uHY=1b7^PUe-h?+$yOa~~bV#b_1m~=J^*9RARZ6~k@RByk-FP4E z!F0TYvcW6r*?0o&#w*LJ3z#(H?_dy&DQp$&#P79SNO^f}9)AiLBXYdmsTGDlj*#Z8_ZA24SbjzxVery{F~R|>mB(W0$KIuP50%rgpjVso9^D?y!zar zNV*#z1?st>Ly}~}3!|YWb3=!^+(6z^RY7xuc}p|vha=h7Ys4Gsk~_F>=!AU&JI!hM z%I>&N+m4Ub9k=cEG3d$-^|5>9OWv6qI-%#8_3B^HlN+1~Guivu=)Ia92Hu5T^=g6C z<^kiZrQoTq2pHIpc=O7O{6GDQ4L@Ee#%u2lEuBM4Bm4L7-@E06wO8$|$H%`buxYJI z-n+KG-sN(S-INo`=$Pvs+Y;F1+LY64*yX zem35$*C?zj4gVXfy1E0V=*T)0K4xScjpoXa25lniFXUeYK2zajT;l_4wg%2WpFwp5 zs$mLa>ZcZHVoW^={o&_hb|N2CaN-~zy!eZ=pNM{6<&PqW2yK!8=_dgw$%dAo+~Fh9s(&Cy>$e%fan2HjBsMAa=i;eBuxk zf%Jay-QNstHV%J7y0UN>!bZlJV;o}`9|nhTCvg$?kEe_N`0+!zI@~d!yEfqd?D+9( z1Kf?*=$_T<3@>N=uSyx?2Qz#$g2x%|uY@hA!(;=(8;+|&esQWlMKw$mmXSLCK&dqc zO1Ug0w^@D6CO_2U6j_$iM~!2)8(EKUd+WvPVj3Fi(M?x-bTvJ#7q3yMR^6d4wqK6l z|N5Nu>wxc9y+<4M1RE}ai1n*KUUqgjHZnhA4c`g`xqeLnt-m+`r(99hpam6Y=EIyjD zA%bXfH{M`^`3Kkry-W`uzsw@ePv~&H!t7&FRv3|wt}we)g$Tv1Fqd)=@hgnZgL{=n zRO1_k8`ZzrP*!OF?Ktd7QN1u^yg1&_;`TP|*yBBIJ^K#$mg=#eLOX+X*r~TBDb5$( zC7&S7PFmt3TVf&nm=nxPVKUDQwBX2SEY{8w&_!;s!k4YwOS2%Jc@-uFzO%Tj158$j z!y@y>Zz*jt+Xp}O!r-wo(psz*Uy;lbvQtj*Nb~*IFu!Sy^A+*NMnr(w%$&iHdLA^r z@dP6ylztoH&dPBw==_!f=T3B{PBr%Q)%GlnpX#SM_I!q3!t;Pp8@+c*S32K|{#|IH z*Q}W^kpA_-)v5)B% z?+A%~4@POeSm{R-H3ia`*aH#g062RzFC&)%XFc!dyeQRfUEN<-yKt(g=Y6)Wt^y8p zkFNfS)$(=U{-}1o@9}%{!Fm{E^1*2w9QU(2AIviOU>zV~K1fZN50VgrFMJO&GG;mcO6U`x)qjsDvtA#}o+M@BF| zGqH=mb|SQ>D#(o0U)X&Ewayg%h(-rZ9^gJcnklxU0W-y3VH$}v5jVLc53bD%&QHN$ z16hrV_Kyu_HDY^&7i@C_VeZ)$p)WXU>7lwG90Vi$+>PZRIsf_PUKb2C^OWC{-6)Ap z&_4qmsOLe;{AVQS0JG44L661VboG8z%lxN5IRE(@ed6Xn0~PcCt6v>{bbodQMBB{M zU%=AyKW5LJ=uDkz?CGoRSvn>z8cuWU`3}9bH~+biJM%%$f3z_39|p?&hig>}hT+VA zcDow1%zs?l%zuc>{J)Z2a{fE|)l1MAJ`SAdg#QC%FxN*Th5_b`b9otgCnl|)>z6$z z)hFrdb98mDOlPjoK(#uBIEH#$iGf4KDlKymRmg-N3Ym8AU!&`PUEBND_n^^P|2df0 zd_TUkS^oh6=X)CH_SgT_oGLsM*!V1gGV|Tt$XTXWxg#Y6>ylI#K*-4MAx%1&uW}a( zh3W;*;}jL=WzMV^hzjP4oQ7{@|L_p3W%CN?<9_0rXJ|cUqTbw3BRqWG(8QgYyYVN? zADNUDFl?lml!2`4-Pdw+qqbpWW?r62@Hvgw;rssVH1MIGUN@Jbnc5FYec$K}K1L1dT#bb*xl%bg0aJEuXi``84CuJ*R)lp-aV+u2_D9&w|j{-?3f`fv_ZZ9v}jTx?MvQgf5)O^J&#!9+-L7n zr6LrU^=LY>UfqHB*~||QOGlC)4xyd5f~K9zs7S}7l^<>cDl$2y12D%$55U9D#ySIh zXTHdM%#P`Q42{)LqyH?eza<`r;f{XJyWMv?`w9~<8%o1(V!}E4?fu2g-~(>#ONJ0i zv+RqU!-Z9_-MFa-&07JQ!*Ax8aC$m2&P}%?HZlC@dBYP-=DY>e zClzOlGTFL%p3+X+25XFXc!SuUq4#B@(3{Rv&!WUU^$Pr~ddKX!0-dQOV~-2h_&n89 z+v09|2Wlld!ygjay>y=}hr6LNnyo%2p(m1RCDK8eRE~XV^l7L^EnI@3-!Pn)k#o** zven~H!k#)d3-vf(%Uq&m{s@$G!V5qK)lW$lOaE9`pTlZNW|yG4&Hc=OINwa-SoFQj zeBfh_6ywe}yTBwSv;Ta)IUX7$mqgDu^F67X5i_5`TR7kJAQIFyvQq3)#|uE#FZ)S& zzF9&^%*Och%}?PU`+W0mc8<7Q0F+~KDd(G=G+ce~paO``B;sr1YgKD)4YVGymKj66rRvA2x!=T&4^I2&8eR%#%Z_Be_=e)S8H}Kr5Zem5S zMxI{`(W{aAGspkC&Wn37vJb%X2DG>FoIszokLS}s5P-csL;&k?wu9&HKcPve$8uf$ zxUOzOkm{}X+o)EzLamLb`Ta&Xf^Ww2CZ53`aKBvw%M7NQ;Sw9uW0`w#244iN#PlrE z?VZ7|lsu00_F?+m{Fa&rkzUj_kIOh!#S>D2Y=*nTxtl-T&=!@ z2Ax@EzzxhS#b~Nt6}-0dzWO8v&Yy(FcK1OP;#14hx+{0%dDIC7vneYZ(G6;x*t1>j zhjOmhAAojF`Y)uMtV>F^xv_O=i$p}+x^z61$M43?yx=JMMn`coN*u*qbk9EO(T`td za#Tu&xIyi}HGUA^(%E?QBELuHUR2AbVuQNoG0~vT1xtP*2RdzpwcH@I;`UsfjOh$_ zs^ci&wbnEAi(K&m!9mJRy~7x8MzNJY0iIOrs_^%JpYh9n*Pfmkr|0Jq4UGBkg=Yp{@(k+XQ0)@>(K-$ zwm)>vhn~V18Lq$Md}uG-@9YoTJ0IGB-s0{D)1`aaaomo^>SWMda*x9mNc08-){f&; zh8t{&o(~a!pASug4-Y&a>VS5M&xgK;*Ub5l_m7To?ndW)sGp29dQNe&kcrNR9u{4C z|HqKK6}0UC7#X4TMTkqw8@K81tn;CV>7Vw_hyDa@oG1Us^P!_+_AEwcs++MV!hS;O z{OzNbJqJ1V{O<47WpypjcXs+CZ0_JLj4Z8K=XuoTz$ymAY@&x9L0AG#l! za6a@HO^lrnJuc*d=R@fPCe)*+EI;X|;zb8ceEybIJ*mg7lIm6r6yr_O)jO~s(0Soh zU7fG17wPK1Av5S5RuZb6eD-_u!2>YJ?XdEVt*S)3!wqO+v*O+zJIe-3M-{;x)hev@W{cJ=_Gyh?T%zp%*T8Uve^Pk-}OBiGR zLqW4|Jki?AdgGmfX)6d{#Td@+Gd>;F%0<*dJuc8PS8JKi&vK^yp^(wB08h<-Cv5i-qF46KF({NF62m85?z0Spc)RE(UmI0Nk0~Yw4&>5 zh!EPw@6ew6&aYsHnFa6OCk|5Af@RkFuUV8?u(i!Bm@PtavtSa2f>}^%oq{k$sBBom zRFtjfwK=^C&;VAi0kAmrMUOg*HA5^H6*+kN!=?Cw621j4{4#kcS6zWA(#c9Qy^Q)Z>hOEbeKZ zLL>aPxH;-HbQV~*_N(3vKXtBMd~(E%)ofpBZMCYW!FtQ-W7LkUm!Iu%-#J9a1KH*l1d|d0r%c@Dla2HJ>AJmFW)28K3%;; zS5F<_7HSj?3dKyITwvHTM<`6mrpnSU+@-Tr=Khm(I6LPO&Gvl)sE zG6RX!3j*5)^(3ws@*SteMf6LI6~@M4oG?K55@{|6dK2#!O{yDPYKN7xDEa3Su_m?( ze+DmLQQTzx7UI9?{A2%)P)RTwp@jM8T{;`Dfaza^`iM}-Kf_=W47rMy;d&4h!|f21 zDbBMbotO4WUW%Qn=WDf1El?z(^P0||y#4P7W$Fphv_U;gQ}Old{&7e=N!J63rXTG2 zguJ1i7mp!7eS(?;^V4`(dv?}RcT;CccTCt=ibgrPk5Ab)ma1tGwDP?c8qh{)-Q9p0 zn@|q8>s@9K>b~|cxS5Hz1{efu>*WTbM zK%U3Pd6?t}Yb*1bHp_E_IUsX_hsqa4;Kn3UH z{5u$N_-{m)W(J&rQK{!aGdDbeEBt;WX0?^mU(mzB?>A^pmao;UCzt`Z?d}=N9&JKgJh!$&(YOa z>gs7HJL&IkRI4(W2^H%kH>U5_GPzVC=iQen{n)fkeoP_Hm4ZgJL+D={vE&lhmDsuZL*sJR?(D19|T-=q6I z`D`|7+T^pHV719-`O>rzR+x2cFPvlSxQKS_0!=?{X9R@O$Hm(bUSaH*Ks#n=J7izj z_ZGC%=M44gM4$(BhG*6LFP21fW2~1Sph8_`dRe47XmS7JL_(`2HK)q+QsT|jzZ7eo9H96rM+0J zj%{hrfwj8N*52U@BhfY&vyE(D&(JOEX)HIv-R%}r*aCkC1%6VO1NQK{Kf|HCS3DE_ z>*RkwM**My5k68~q1QNk9^};z7z0;^Z*fiCis8KgjWYRvfw+!)e=+8QdJGbBZ-jid zT$HFBu);IZBa(IqCLm%S>ch*(T^=XzzX4fPSLo_%b#-B1C+|OmYIP|rRFC1G-M7T$ z_y6#Hnc6nrmsyOA*XH{&N5Mk#fMYR--wiZhs*a#DSbI6_u;$r8ddU8MOnxsz#H<_l z{z0^;3&7&{OXT}qSPD0(y$p41O?SVe9z$`?e|~;&!22csSU(@#Ol{Hk$?`ku^{E<~ zxjvl$y8ZQOi=-W_PuYM|?`RR#co$#ahvQYU&;o#og!b$#xK~x(#Ifzo4Ln;X-p0mk zCRpC$DNDJ!VOQo2eCQ46S37Dj`n=*d5JI_pI4=*m)y0G)DB7gOUiFJWAx*G3W5oO< zoLAU|`V{3{{eWC*@oZ?F`UuP%e)GxQxF6xI$}s+%Kz466i-q8{-g5klgUoD?dYmH* zPV-==i1<}^8!{)j5D!Un@Y|==j|pC`(FreE1q5;NO)*=5#y;`n#$^a{*Br~##{IT zz(f7&SPm(Wof7^RX8atyU(fe1p5q{p-%lh@$DMO7H&PlRDZqP`5;=H2b~EN$M?^J@ zIreCoiWeQ{OvMrC7S*30FV(;Fmg@KLOM3NL__3%~|3H7bpZN3c==XaL*k3&(u*;#; z(GnEV@AoY0%=q1%k*&Yq0~;_u;Wqh(5V!F`Z!*&Q4Zn)xa1Zwd z`r{U6xx~CVNIF#%m{L{^yMD_7rA-(wqwff;@JHM{=N?9w@FHm(OpA9GycxP6)ykwsJQqW zPKRRv(f6Pf9E2&to2Pef5KXE{`;6z{U$H2&B>p`p{Qfl&irZoSg;=zI4h}o-k&fh0 zqBHGW2AXzWOGS7piJ-IQ$&EmQcFHdl5p3=uaC{Cn4neNtQU1PAc1-VMXrzW3y=Q5? zD~^fNJKWLhf|lJ6S$ZPSZ*VN3o>tJbZx{OwrTZ~;Ec^bs%-FXEvoJiv%sXcuI`2UR zc45ADCFGc|Y1p>^7 z?Rp*m@IIG+hpBH&Pb2lXjh=2=&sxlVYkY?~dbYt1bC9O>e2C!~oX(-1ji8CsYaC`M zeP+C#&4?-SV>9&(f<0ItFam#aqqA zuqS$}>2BN&&`c(KR21v?!=FR%%!d4h7+m}oh&A%;FL<5c4sTtGlFn85eg8Ts>g_?D z(d4{6T57cM{d8*UueEVQpw6L^P+bR^pM^oA5oh_e_3p+&%zpePADq$&jW~BRH+1fb zDB~~f_$U28gZMLJW~I0rFP0v#-axDTivQIN3UoPzQhMKfA;8l4Xca2$ReOs79hZ;H z6AAl7(3$Vp4ZESrtlNJ2IRXWYCa?f;cm;Zo?YH%QV;qN$ z{B;H9l7-*9qD2fCOaop6O#_~%s!;kCOeQOztkv=6ZoHGhhCx(Gb6Iz$7$bTJ3x96_ zbogne3huAw3Rn7hn**N)n*B_~75$tS-_He3KgqhEa8H3;<16}3g|QmXy9f-I*9YK0 z6~Qn~Je07XRv9*;{2we}LAOTpJsL2pHNMO!#Axml8U5YFYp&Ipo(o?1bPbyBUpo7c zy>cCUj=725zabp_t)kh^m}}6~*s_hb6@%uOWxj;c|AnU{mNh_EZqzNa>;iLg8;S6#(eDWlm6AWkf9qI!@9P06eB-8Xw{5_kYkq5yI zI;ZYJuc&U;)sN`vs}6N?>Lye>`;PBJZevBGVD? z|G_9`(Z@-*_x@i7gG#b7->~tcKW5N>p$!ud;~Q7by__Z% zBk;vpC`sw-Tc4ESEAj;jZ?KfHl4$ZErkj%1A67_OERLD^N^9+$;hRd?3J-+LU* z5ykJS9Q@>M#B4UvFYG;rp{b#u87pUzkNsbdxL6s^(KB*q>G`1)j5T@eokr25n!u93 zpB??aNs-B0@_ybBxPbZKDa3}^&+vW1ccEF2KZ`yBR(Tk*T17Clc|B;}3eYsK8Q1ug z`)&pfOl$I?w{Q!Qq27g2z2BfD`47me{FvTn*-wVhm`y_uP@H8HH!h)081^rYz`Sj_ ztwHQl&ESO#FeILjvENo1=5}t3C$od?GO7*gL-O%^;1Jl>9Nej+!QHem4{Gx@9oe9Oy*rljbpn_9p3l{A5@5Oq_QjWRvGrF|y#hA;nYv|^_ zf$s;X`Ob{Mh7OB~yKynNW_qQ{yyWwKXd`( z##jl|&OfWqity1JKjZzH%)3&PB1cO$=#sypxIUZ&4!K%2*BE3~A$u`i_fyKwNL z7Jh3Kjv2pIk70spR&dG+EJ>@>?N>)Rc{m>U4$PJ6=BpTSo$&WkaR=9*!7sT+-d{H7 z9Bp#U;WRh?FSzRS4eZEw!K-F7o6Cs%5HvQS>Roy}l>P$3(wYY!!63;mRU9Pd+EQsQ z%lG_x(WFjhOKdh~N>&+5FrwoRcd+M=#ebcv<;JXLOktN3?^qL5o#@B;6_qwzu?jn@ z`OW@=Fuhl)i=?Bh6)?!3L}SKl#>yyT1Q^(B`sIsKX9|IDaTmfc>h1$Zc#>FI&wiu% z@D-gW01NK#PT@2~KKvA?u+IIRgz>QOKrLrZb8(D=LCE>L)b|g+6i0i){E~949)Gho zj!q8u&@^nrRxvB}8+92XB7AlfN6Z4XkmdxlR)zTl1L>n176ACk(~XyrMR1qSE~BoL zYITTIchJ=z9pq#e531E}deeZ;%_;xRq(!5+lDLFx+UKKwh14^zHuLZ2*?-Tf;p<^- zzF3DppRR!s%uk;pNZZd(@5zKhewqQJt^BkJo$I@rj*w9AApT^wI{AtB z5GFqrL4bc4m2R&Ef?WQ2Uqm_`G_G8=&bxxE7S>CY2RiCD_zU%P#_4JYqbH}~8_{)| z(e;SY6~L{ zybA;10y0JC8*^-_=QFX)X?UYFyce!_`o}zv^8Wxn_g2)$WY8zVtMfh*2%cNW{MtYh zFu#sR3+Mg=Sm3O2WI}`hHw_cjjTjBbgZYvz_+q{s zj~YvVEBGewO{V_spsD{u%7@Y$;`Q%DU@)unCq~PqsbI9|a*a`{u=c9WxQ5T%4`KHG z7Ketpx_h $ooVgf>YHN!tN@@Y6j&(<5E2h}5VHJ^Q>`t+{OY^_GMo?rM|a?!tc z&-uoE0RFaVVN!5R5*|_Y=ikcHziqREJ#HM6EJz^0ut}3=l>EcyksavlaoyQJxHyDH z^7Qh>%OI?}pffpl*7^hd%klj4snqLkybdDfFQ=c=(LYPNT{5CUb!ch{j7jnzjMzj6 zuXBCD?`_NMb|;qGOOpa`dn1Uu%bQfjK`m>Zh>nX#w2x!*)utbh@`*6nHCz^ks2?i z#;+II8nr*n@4x~+M`RuA!OUET*VB$NX!*~K`y2D8r~wQkos)400Ud}wX z+Bc`B&@*zRC&hI_m9M&{tj6!F@b^D$U`|ce{3`#V{-+(lpXMu?2exi`E*iFJH^Em_ zJ=Ry`FNM&+foI|WilPespwrCq^2*{Oe_3UPXHHRBxvylPE32*wR{2UiMV`^MbLRM} z2fFggYHG?V=6Z^%=hnsViL^`a`j z%aBWMQVy`Fq$IzfARiatWpr2!zpu_expG2TiEC0pX5oa1h54Cd$L37P7BYYQn1a-H zI1@9o^4nn-WadsT%*~om=*2&lf+#;Pb9#I1Nm*kiPR*L+g1MfGO2223&+h>OasD=F zdgl2S4RoDQT2xU|?z4h(0-E_MDr@JKN<73h)!`HuDhC8xv^EuCR!~}5TV7Ies^3#u zR0TYLOIsS`b1I4}tE&;ckgqBA)RbN38z_S*Du=I17U{vnMKimJ8c|hQQ|2#Q;Pd!Q zBwBTqB_$RclZex}wz{Th0;bOb-@xKxSB!G8YtK0&J!SK&MvR!3S5%kltC;IA^_+5w z=R|*HrKcQI$>*6Z^Xo+92@^}v>Ch&aTpH&y&&{du`>HF7%Ey)Y%1g#n)-pACIOokL zI+P;MptLh*m-&IG-#6D+9fzwcHspkIoaVnrj<{ok8AaZQQVFuhd|ypX5yq&U@Sp7( z6yM)`J=r}RLNUkbId`NdJvEJ;S)U0-6(dIE6)l?W%S9e5KWD+P5hEr_T0PezbrXCG zb=dW<1rmeO3jL>9&0PyB%SsUHB|fJa)6<9%{I@@K9iTO?waZoGhxdy;lLxe;WJ(27 zdIB|`84Jr050gD3Jtis6wC!@r3(BhfwMFIaXkVg-DVDY|%4v+N(>}pCC;8@JQTUCI z8DE0tTzSS6m6y*hDxTLL>AuGAA!s%`r(#a!Ic)(x_Y|ko|6t#g3an}|3zIUmseACN z4ERaTkc(^2Yx?SH>2PePvwLCplnKV_%19&y<%|W9$aGxuab1tCMis7&xJRvDh+9bT zXJNIk$5zyZoz7#pdT@Ok*VWh^{DNyeHmCitH&4L^As^Q&Y%5oh#%%!~xwYWx!dsoQ zaNCoDYcsC-xUR;v3fCRDHshL%8@JWuvs1&A67}>Uty+S&r*!Twlhu{!z%|y5*0N$RP(o?x{%R99&mE7m1XUelZfc6W3X< z0Uumfw?rcU!qv4d66w<&^m^EjYs;ocWHITtfhVphe~Cms!8QK_=*3|{$|ul^>mFQ7 za9zC}cJTTI#)+%zE9k{F{~O>AKkfNvBr+M-{C@*a`U}^Wac#kM2d>ROKrj5X1J@K> zXYGwdE+UOU@2dhOQkS><&>c#_K`#D*W6DT{Ccv%4Rimx|Bkr4;FoIql*2l zvt=?HIxV0~*1;vbWEy?@AhY;;_`Qv6p%J2eeSpI%$Si0h(=mfW;}0HZWId?&LiQKP zUfNdHOQEcTsgJ+eY8%FTOIw+XC^IptkJzn%Y;J8Nf|rS6SsQ>Wtbj7B>8>2ajsnP!9R&z~}*#qw-myPSirsWYan;4Ef*VGowi^CRO{I9gK_mo zZW|DlAJ?PnY^j#HaSrN-p&oB^nem{0YOJ1fjrEDzFGjsLK|Srg6ZO+k|9kCaZr+r@ z9{TocQ(qjl7xOVX{>wQ0@r)P7U+>N?*C9BIIW8)Tu`&2SQ`az4U%>kDW^NnI{SeD} zeZ$-Dpo+RmAe-?Ux*ARW@6ojyvVQ1l4^wXTwxGTd^%B&pX(e<=Vc^ zSaULPLerifIo5ur{`cU<^{o-Q@MOvKpBv42#DeRdANAd%_1SUtTn|frqn_(zV?`u_ z2USM@dC~TanJuUvjP{q(aZb+7ck)6*w@&^0=m~*p%Da%98}E!np2ggV%180)baqD# zSjSnwjrONNzSljG$mwkBrQav@=$fzNg8K4N-w*X=cK(RY-CX2^2sP$7d8r=qB`YJ5 zC#X;CMVw_bFU_Z1mLsvTaJ9>XAi z5%xX57mrfNpYv)Y(wY#Dr0DpF-wMe8vKITjgm@hP|Fw6mv2h*Od1NZG+gOVHlKZ1c zHg2psO|#g$OD;*HHTYUSEIzKq6(j41hs))qv=zx^c9$!%g&p;!q-ayva4IKAni6O$ z$B5G^Xut+WkrHjqIB|c-NK3e>QY(?GxUmbc0V>%2k?nV8&e^?p_g>Xx(tjSu1>f&rUH4pQKayNM7m$;);J@>qYPGi_+ZhY=%SG_N`ZCVaBI|uIFiuy%zxUs2 zwV}{{r*VD1;im~n^*;#3^uh1dYJcpn&zMht+;6I5<|Xm>fdA9~UaLLg&)?5KSI^$q zf+g_3TBy|yBdygR5AEMKjEP3i?}T@H;GG^YJup3BJEEuG(rKnK#{a*&iOeU39$et1 zAkPy`&zhePST^;W{Cq1vfAUvs1aHPos61~et^u2{b~$D!uB4m5$rWx9oA5RMoz@-{ zL{H$~bSTpEHdl<)A%$CbLrZ3z!ZhhI1hd`({W=!_b!UQnyLEOt+X`V|tzGzF)P;4>3K=G|hC7=@ipBrd6irn4V{Pf$2KaO{QB+ zuQ9#Obl(G9KGVZY(@Y1MPBEQhT4j2U>3OCXn65M3WV*%l8q@1c_wh;NA*P3!rkM^h zonku2w951x)ALL(FkNT5$#je9HKx~@?(5<9Gd;{S&2*6I6w^7TRi@{do@aW2={nO* zrdv#}F}==oU#~LZ5Yxj<(@Y1MPBEQhT4j2U>3OCXn65M3WV*%l8q@1c_w{l4Ob;_n zGaY0)#dMBomFYRA=b2t$y3TZy=@!##Os_ND$M)zD)5A<{t)O?W#v~d_yPMGC-)sW- zaUlX9>hHflcHglXyZ~8_b;eWi#7B~y%jVH}%;}0J+COCB@N5HU8?4(4djgPoXj3=U z?Ti1{Hq}m|Hw*S$O*m#>dsBSSE_~37C>NX|o0RJy- z>UJgeKZxIfq=;dh71ZyT)lMu=RuDOt@ls`NiM zVc(_xtJXkljKu6F^z+hyeZI^LM?v?f1FDDn?F8drVtkG9Uu66h#uelDGEV=P0_C&u zq6O|_ycal?dvMSK=G++3-(~(Q-?BJ9#c0As=3g7K&oXTP%J|Z-#mzY}qW7Y`l)uQ2 zIiCW4Kkz;3ZgrOXt;Z%)g9bmKVqDJ@<4-U?&G;DOuLGz2WgTqxkNEADw(x$w132+N z-X!ODF@C8DzmM_e_4Nb5_xQ#g%{O7p;H~mm;e2HM&g|-};cu1msQUkj;XkN8{V$S3 zgNDh~m%)$AU@h}*!{pN{=UWE9yG5SA&v>)`rgNJ;A@l1^;O1Ieqk1N`cW*e}9)Vwo zz}F-29{|4{<9p>9Td+BALDa!UfbgX=7B}Z!h&~EDte&3`eslPY`vx|ddNzXpn-Tc; zIiIy>Z3gB%2hlh-B2*uhwYcm4KmMc@_S)Niq8Y1>j-*Fcg7LMBw=d{P75U4S0;};3t0*!N33AJRiSqxy|`1qI54Htp1+?PV(8q z@`-6~!Ve<&Z-Pn+%jYog+c~YDbVcw#3Owd#x^$PzOlkMPxu%nZ&@> zm#)URhL(JX`J307Ka9x#ZXCdewJQgl%DwnUHed6;8PP9B@NY1G>_N+K?lK|zW(0o< z2l!#-RwMAoBk-4iQ$2hB)Rt@BLnBI`jUs&e4=rxq$0Ir`_`1c-`&>l73_Pqpmzlp= zpS%&lUt|8YCOw?Oii_#{ME-9? z;Ct|5iOO{+Z7w2*9|9iMuH%N^U!skl1|GJ)dM+ZLO_LAyFJH0g&HH*p5B_|3xkJEj z$6KQ2bG)$#{=bO8l|C_^!UgXXF4&JIQ-jNkd2(Xu=gY`+D;i!fnWIO>lhv+dqWO2a zl{_*Imx_+5-2Aea$z+h>iSc&2sO%&fH>;hb|1L9U=cN6h$!ap8k%!Z*wR<#^%|5IL zkB#?dM<&L#4$rv5+-%NNcakQB+uA!zG0=Vk{!z!7DHO9sdp#aKMg1AoRp`ZfSGj4V z)8&e3871njU$W2qT4aMpofO=9dP^sd_Z3c#FE7x*beQY)7zmxVeQpP0)M=lApUv{Z zZYtMplbZUKyp!ZVRnk7s41Hp>QycFBFMMd)Nq91W>N&ppMK&-*eA3nhV5F0;_-8V1 zRtIwKcpEtnjZXCSj%r3fthAmj>XY-u zncTddtrSaTom*Z}dAKRfd+_m!cc#13;Y@n2uvpN!QYp8p;geNbRdc1>f~RMf7Zz5L z#P_7ZSqZReJ$STtETc2y12hBl(D*T(8D?;J;Hc8vsENVB$xK#fd;3N+#F!oHuP2%< z7q#_!QF`Fv@!qkKel^kepsuV`l8f+@f(n2PIqg<-vL4z5f2^c4=~Y_YWHJTjXGwE9 z2RyXUn>e%Rmf)*Zs;p)phYgAB>@UJ|W~Bm=Bt=0&+CGjB@IBXO1b%ZmC7a#~+}~!F zD_%zRjZEl8?~GpX7BqZ)s0K#Gr0twbTc@CCS)&9ZJ5G9{$)k+a(c7J~ftTYiE z%P}r@JIafiRi;KESH~F`*6(0bA_Az1$R_oeInVBnR0dih&!A)s{6CYb)l*ki^gTe zbvnK3lFk>FPC--TD=VZrsEPSXX`ZSv4){jcYZgBg#2skcZ@ zzeAk*s+~vIiblZl(}>=o{V=; zbtGda?HOND_SJ;fV8)%)ih3HVo_lm=brG{h8FhlhPB)FQ5g6z$y_ADeDZ6R-(X|K; z$qtP}b*|)*u5RrdYY{_#+L7g^dL;*>UL?rr*^mmE9wL7>6A>R)5`68gs0FM&iusn# z@`--;M@i60{4;L8;1))6( zUnx{t`XEG2I}R2NBk&l@E#|%8^zdn3>Y#L8VCHhvhzMyRDGftKLV=?BL#DXj@Y`)O%*enk7V_47Q6VW2@@fP|^$`KVYjc{Nm;w$>Y(X z%3I#->XK(xIK~`9`6l$z$428^mPRe@2v*Y~^CDCcm^pk>~92qjk!*!BAAY{d1rO;Yo znvogw8Ocn`7SG5T>AeCJ-y(~Z$hkng7HMqE<3lj`+zJg+aCC@t@GFT+f zSlRhUt4W{(^I67=zf7`=#zU^U`)Nr+r&Sr3)+=4m^5*jqJSSnw8WYIuXfnIm4{AMA zF59gIW!RYWP8tfWsfz=)udV_(T|n;+B<(8B-}SBXhDAs7DxtoGq&nqK>-?$HO&ghZ zDzC*9$e|p5Y^Ng)YDwcjK>7>|0NLTp7EXHQitKPga+HOr%m;_IZ~PsbT?{E#!RZS0 zsrd|u=_;S*v{svUF(HD6rnN3pLV9id4x?lXcS|4A}J&v(~P!#Xl%MIM-M!CjCvz?cBj z>-H!@&MB~@Fy}~SUir?EqNWz_cu)%&TBC`1!)PZ?i#hPwpOEQC=e?C;1skux{PS;A zsCF>}0{6Q9Rn*<}`7)P8#|7ZA9{R?q1A@U0#RrvDVg9wh_} zTSLBK*>I?vUs`Q!;v8cse_C65(r08l#|E@HM)NBfS}OcR>pg!nN#T@5KL!uU0?jpV zE_m`nGjxsRPJ1_4F1b~g?P16}z$y#`S+~I3L9;QZ0%!qgO(i4{<~v1wq2lG$g-UJ) zv{JJ4l*I7;H7|~rVDXvd!u;$<@V>)5(TB}ce0FsaDJ`v(>@N@z`qp0HLF2cQH=m;f z99x>Ns5q@|R2AGew{+a zkJB*Y4`26^M>UKX`BX}J@xKu|&IzRc!YA|?(vy#-Jd2->&}lA->Q6jUe}>g8BJvwy z;?E;g{6eLCNiXeRhm z^wW}%X>)!r11H&)^y1eQ`>stOdPw?B(u*9Bc=*c~|F47OIEAonN&T;+7y3Q?;!j`q z6T4!Q9G8l54w6nN-G}w37k`@Rt2V(jrxOyB2ve#bzT#cDuHaNYs(}4IR<;wGa zBSPgT1Yj!Z<({qlOuQ8Qv`IwG@7rAdYq*C&10v}oM4Qeq`AJ@_nG)KUlsGvHOS0cMth+8y!!+T|B0Ebn&Q>@#NR> zrVsK;Q-@BBr#c+0lJR8h#r$O@sX5(q%N9)So*PdM-59;EXvd@eM@}|vXg6cl!)j=0 z@}u`uX*{{Ye47hOl25b|KPi8GS~j*co*Z|7e8D-(K8v0kyFa>DY-#kc*s|h{&&N}- z7bnIGJsTPe<4up{ol<;i@wnpC#yuK6aIQ%zHS<7|*1C(M2M(5`Q#1FrHpG^$yT$BA z4=jpk{%p=V$5S26rA^Da#FN{_Q|INyTQ(*-dY9RAsk6Jp^?b|5crquEAH8qrj!kQ~ zYkDu|xOOuSw~`_v*X=20bv|WWtE!yTGkRdN?nFHJXncVdVkEwxxA)awzaBVD{xdq# z^0d!WFIwZtH>~1?rhHEHN~k3H-AE~+IE!ax{<3(>`e^fZQV#LtXYmDPx8<*XI7bo^ zB}QTYjT<)}Uy^(*deOcjW6ooA5MQF25 z+B#H}`|&eKf?0WI#)&G*@xAEkcCCSgV6=2S!2{6J7#_rOzY`bX5i;sMrbN<)jx8tK1{lvvo z@^zQI6k9y`XteoF1R)B(W!bD_OH#2&yyX>%rD*e?RV=l;4XSj#kG6d01r_VQ`o}XS zf4xgj8X9Asm$wkNS$~x#{maD6#F~k(NHZqQS`EfKV9Y-e7);$Gy@g7f=OI($A zZOt<>k~14;x%N02yWcZ36}x}k-0bayA9O}iq9U`sDE8ZfZ$^qg7D{=IWqC=P5cEY! zszZ0NtYvld67_d!YD#C5zvS|!zvsl8zG~OFi{x(O+*vzDqDk$1N*7G?>MbgoQR=)M z8i+f2cGb+|P7r3+)%@~bVSsa(%Qsi4v36C^=(Zb@=*_pZ+WffnW`?M(|a7A=gn z?^|JK%UCHAsTA`(OH#3Utwa2BbjFreeO$a?OuKm1SIN;g%M}zQ}j6ZSG<%A2!bLEoUTqPBR9DIo^-t?_BUo zBu86P-)-F3+S9kcBsI8u7vs;?U&|Q@POpEW^Cv|=lA5~W)8gpiwiy;h&G%{Pr6S(7 zb#kq5XqZKQD2OuCfO`(rW?)4kVKdVv44hwDKlpY_(g^kt(U!~P`qo}zsL6Bdpv+P| zXI|@BLW~tslQR3$H99nq7Oy1vtW+WyAe@)0UHe(_rn7rQ5`&~?Z5&=Eg>|Cuzp|E% z#b(Tt*g2j$JI`kB>^$xF2PZ#9bb9SUOiH(9bz-fkO6)1=n+rr`X|gIead&B|s)y?o zN|R^wShvK;uTLyB7Bv1O__7k2U*GCQg)-CCO(>lFw^Lll(fdlZ#^UNW4t0RKJ$n z! zT9B?meVqk;#e$DriKgS-)`!1av8udve+u-6UU_tir?!JRosBsnDM==VX`v4>HQ%o} zYc%{!l|SC7mf-4a)A+H}#LlL6n0n%>h}VARFVj(4+CCQ#|J&(nOiQNy^3Zs7@htar*lbCD&%ugC$#~YE)~3s49XTsyCK2TIIFDXt;A2nIYq`fQg%{Ji=r(HOvh%& z-HUY~ZG7e5rTO(wt}r#ai*@c9T~6`6s<(4qyRyP0+qi>T{6D6>vB|w9G21!Xa<;VK z>+aFGRQV?pSBq`Y=J86O_u5%8F`YzfrJV7&E1zuj->c7oc+K5(yk^vx&4}0BV7z*5 zZ*rzI25*mhRN9jT+7`*Kvp0Aw_Sx~?$oTmmEY{vR`B0H$Fzb*n>_$q4ZPDh9GD9FY zWHRa;x5SpmyK)QW259M<^M_@yCCRLifsT!MkKZ?};C6+$iI!(&Sggf7Iqb|H-tle|IB& zn!AIPfqh!Qn~gB~T<>D_F3^}Uxp+37To9K7bHe;rn*67emQ0qrb0!hVwwE#W(U(U2 z-|3_4Wje?Ak(XQ>AEg$ki8A);_s>jMIRnLTXSJ7ybXNTlTW~ZbB^7OcPbQR{Gu7{( zid)=lfPDM5f;&-;OPk$k)|L6Ji zA$f$h*>U>eTbt)o4vRNA~Jk2cA}#Q(e) z{nbue;L#i3*rp!cU()_h^Jt@6d|;(lR>wcFA- zz2%kv`gB|Sbi~X5_35_u>31*w*QeXsr+2*YU!QJkpN@I{f5oTq)Ikq}FtRMpndD{Et_`%0V}iaEao+^%OIeutx~C#@{pH`pUGeiD)2D-2 zf+A00FM7vc$}KsMcafw7CGuU zO{P-4>&}&lYH#m)(ctYpEDr>{z1RJ--^qg)j~(FlyhDA;EI z)Ld44zmjyYht79dCQ>*ZfM$dQvPRjd)YA~9&ghD0B; zmmJvDb!-{yO&j-@1wcJAno@85PdqiS%es|bPP4A@FB2;^ak|uh0Wk zYF1u+LA*!)YAsqUI*&Kal4X^WpK-eUeLrvc`~MH}qpQMXU5w0yejAK+xAq+!xm_48 z>(`^rf0yEP;imEYdp(xL?5Tkn@5w|jnqy9!W#3UTE97N;DIDd+OsYZFgMRehq*c1E z!s|CAF1aZFQdQ()bKIkCR;l;Yh19wr%U!?jVG}3GH}buw4pKo|XZY=hu1{aLD*H0@ z0!eBUp`7nd8<})G`|FjY{a9$w{H^cxY&UoEQ~Ws#At11w3+ z$cyDadAcP1rfXYTmYsZ3wB>NQ&M4wKZH_M&G%l6*CgRD)d9F3|(oM$Zde?bxwPe0} z5N-aY+T(0Yoio>698aAy&s^usaLy3p`Cd!3x!mN)m9{tF%xJ};EeFV$Bfg;eMYLpI zyHlDf?_8REp)|Q@mRppwpuC-!99-%Cn5=Y`>goCO6Ms$@f*pI17(=xC4 zi5y9JoagA$)HpFyQ~!yiUatuzpB1~@*)s8QY@RUVUa?=|Ep8U_e;0lZ>zQ9z+NFK>UjIL9MfQrOb-eWAva;Uu!tyDtU&yf+A^uA#?$*fQct~Wq z(Wn0=fPc9*ztdb$i79Pjs`U?PJJB9I@QoW!`0uOy+6YR7w)g=e%dT|4b%;4-`$HGy z5_oghH7_hpE=bFV*e|8v6-nqaw9=H(5^dI{-;$pUty$}ecR{*rpKOijm}#MPWSLY^ zS#Ktb{%n+b{Cf?FHh1$Z@Z_^5oqSiC5p%wE7x9c&zcT!`^?rC+nyW4FLu-yHA~$}N zw*r4~{x9@W4$ptZBgfy z9xrE(f2&>pmG%9qj0z_GR}We29Bppa_R&^(?Y~CLvG?L+a7@tEw2!v`(sj7099=Fw z$7?WuX&TJw(pY*=h2%!DTE>y zF8Lq>b3BPtgAygFvOI0fi<8TwrycCpRaCtvFIz?D#YDXLe5n-j&f=x*#AKtDD}L>h z@Pz7h2B#XOw|GB&m{XG4%fA2G`k}-IDjuw1=?$bMhm!&o8Ij z756^jG%tNM$2e-ml-AXPw#J^nODe5rh>!HW3F!T~Ny=;Qef=B_dF5+e>faNZW7nbi zeO2aLYjv9B2GMVX^S!Tl8^0TC?2DBNxy19>R@M9Lt%m>RrF&m)>)V6zf%YIjv_0s& z$@buKiOkZ}wrvm2MYL~Ddtl@@-5xB|Of)^#<~>c@ikVbg$eWRQ;u^m}=&$v&Sl(2) z=mb|q2WPynYex7lsnIFh4(K?(O-u2mfmWixh@&kjOHIoYGm^1p6Gnqmv1S=^%L@pl z$yPU2Ee-d)UA=TFudqzbJ9dkunKGn*YrT%M2?&^cDf7{gm^E64V|4zTLwRL|X z{+rZSh)nj{xlbe47G*xN^(Jkx zx4yN-^VF@sAN=q9(0}KLbbRgBh=sjABu_BRcmr|%-}xasqzcZ<{a>CRniQBHIwo{} zDA#ms!TI87^Kfb8z57L-uMNx*HLsRnbA5<>yV+R1zw;Z>{?e#=6EELL8pg@N8$9{> zh>YiXXKT+AoT9zTKs)jBW>6x_#EVY#c{4BR`@!hEKX_`~%!|&G+nJYj=h@%k+lu?1 zEx!NjY|PnYKf6ptvh}lDVdo})pN#iq-c*p^zoP$KEjJ@x|G71Gtde%9wZZngZvN>r zfq{AAy#@K{gp7{D?gO(Aj#@@*(rxF5X88H?@4Ko*GJ9A5JvU98bKm9PSY`Ykrx~w$ zznU7dz9HNE&@O@bp*KS7`}C~!JuyYXSE%C3g5jOI?|!lT$Kf^^z#?ilfQoO_b>RvSqRYCngP> z_h3Yy+&#B-rPZP%;nw3#CgzH&ttt7IPO8hVzjof{FoF6!D`S4=0@O2GB;ubbM%43< zzgk6iGA66!eyLek8)FOuDR+6i znEo-(xzXkvPm4O!XgN%@_yM+U8n5f+!FX#*^lpQ8$=yF~{r$&+K>Kr=9A}@OUi)ut ze|FOfvjy$X>BgE(_QHSl+8;i9@*5a!f1cICmL*``524;}j%@SfZous~s<^I|^F~)2 zOuN)(R=s7JDDp!mtb^OcbC>n3PrR>feO1o1ZJ&l|HE{RSKfDKMIajo=yTpzU_*B5% za@d)WGeyp|!|}!OpTy=xTRNELPDgsu6&>%|K7GozVoI>R_k<45BBX;*m*M`BEBQg; z-K3b^J$$Nhu8R=!rurk%=F7AUu&PTn$P+wyPX90SLsj0~i9S>)lS;m$XJuK-ljb?X zBsnZe?P?z3{ZZ;=oAz!ufzIEyUDRI}^~O2g0~MJc*Of)v!vEiC`>>-?W;>scy0rc& zaQvKiyfyK4m8SD6$%n6G+q7>3RPQj+>-UW6^;TWX?hngGh|D%<{<5p^hh>5JZq6rq z3AZC6hWwEtNW=(}{iLID7kO9(B9*r|I=OIzG$U`tjM8wvYRMfBSg5 zH1&bIlx^8Q-llc4?Ni79C)>w+Bzh#Myr%C&(+tUR_Oaort?WOZmnzu$58F;;jNc~6 znLvB?rl3H3R&Fl!#&doX@dNs?;cCYzo*n+U(9Sd1N!i8mezCcU)3zp+_q5gd!sKGG z`dEFM9`D_18XvoYTE?4F2J(ZU(dJchl~*rsG9_ah+!ZoVw<|)Mm&tn;@}u65`Xwio z*c&6X6*jrjrN+A2>?@tomaC+>XdGj9+;BG9qRS`!A?+M6Lwe@5(QcYjev_X2dBfTr;iu$+?f_LB*qxFgf{pFlDm(%*J{93>7b2k27cWKOO zTj1W^Oa5xfUT`U)%w8s{(z8m^19+NT!`V7cQq10HZ_(|zv25K{8SVS`yf4!jcwc6Y zw0PU(eVOiVEW&l4_PLY%eTAfXze~Epm9~`Sk1RZ6b|-!R^Mfr|Us5jZymPbmPY20y z_Wo&=X?Fbi!u0YG?>=0Xk}a4a&XgxM_l}o{u~G14Y4TpZ(b798FDF%_=b2xLm6rpO zFT|7Sr5$Bek4qqw>iTT+klSY5Xfs!MD^23w0uPB17cuf;vA;^Z)O$c~&dRf)GQEg+n_3X>15u2`tSFIjIaD9XyS4Ae$S;c2yxH;HGap- zarXCnmYETaAHTXp*t{X6!}wIZi!|$(d}|60Q%qNyn71>~hZ+S~`lmO6fA%EoP2hYh zV*JcWs8fR17N7s!M!7V4NsXLQ!#|Pl+uB8&Z&b;ukM#v0qs82+NM&o3&ZL{(k=lDo zxu$ssId($PW}R%;AK3lMn{4;XOmAQ0CTreva$at{N?lnhEt9t$^VU_R??3F{*FmFX zW5#Qd!|ywrZ&T-Gy90L%GuY?IpXtb42bJ}Gqra*zvd@G6U^_QC4=!`C-qZLk&wq=q z;#_x&7uQ>(=YFY$t*6*}=jx$b2bFvm^YH~TY;pC~A5^sd!VG4br8LBOSa&@|_}18! zt9Csq|LJ}1R`}^fvBOTJZIzyds;5xwksiausGC$Mk+*xzyU4zk9HV%$_5y!KJtN3N zo*o>i2`-oawn6i^>Gh!@?VoS0G+nmE(s^QctNEg73e&fmdViL^D{s_#)#g?++PqFe z#71Z9t?3T^Q-w345z7 z^GQE7Rn)8h^7k%UU&nFQQF}&>@cY<6jSvgXsNF4T7bgpfHqV#RHKO9z;ILgxZ(S^@ zr^nlwYF8BQF>r1yVe&|}SWI8k* z<VBBM{9GGx|WXB@S4ZK@l;v>8v9B)% zs?Kz6m9EJSlkJUs>qyCx=F_FS<$i6s&8Wy$-!Jj%lI=Eig`%zv-@2M)icfyK#Y>O% zDeE5#O>O6H#M*aISA5NTu~pJxXTKNQ!*u0s@5Qt&mr=uZ(MxoFfEU&}rjP-hbSBZ} zIYMpq$~W~=?$z#}FL_p>$D_?(Y7Dy9R=fjyzjnEkl0It}le(Qv)%z|Cli#cH1f}F} zi#E^pC1v*R4*|*JeMz~S(REf{${nJYo)eJV)0bQlZT{Ar)YLmhFC7$+T$i$$kv5>h z&rGN2r8@)!mwSR@=E7*RzK`l9zFqWEZ=Obu?c=k>o@BK7K#|hl!jXkq@~crY&G=8_ zU=O86FP2f(Z6swfJ@Bc(C0;qCa^&x&x|v4P)|mCncAg{f2FvbhZsuQb_2xH1@2~9N z3=Cbr*gRb`>G$(~+wB5Q^4~hnv?_zu8Gim-+p+$DKdQauir7M_!Vwqmu9tO#hIrFC zx5>zA+QP*4(w} z$qerAUYA)|cYkNXxNmDuPtMNf$~2B-!py&$^F3PsC*wG`RbNt0pO?Q`n{nKwb!YEb zY?Gm4EdN7O)U7}9{V27-mVWHER(-;|4O$oHbRC@P-@HEiv^Heta$bLwE@Il% zh5GmN`1h=uKIj{Gu}=Psn`@uCXa&t|pI( z`@_KAJ&zeswu(uniswIRmPXp2?MVe@V{~1oo3jkm<+~*%smpz_4$H4E;qw6BTc1~H zikq&_-n6AxpFJNuKBe_bQw6;KN$R=JuMqCWR@xZsCqeAjuft44i}P8(4v;I{{l^b( zmsPCnubJmZKB6vJxdy5)21h8_c$yPPuFhx^fY%`zOi}!&d5)qi*Z-epw8_!Y0qh*#z+SII=s5FesFbVVv0D?#E1P& zE-6y;n|bl3<+5CEZ~0rDrc{s0_?!2Kcu{Ffd{@r^ZJ{EzpYvRq-35}KXOYT#TW0=b zX@#~_%Ow5nT>1xPq<>IG`t}D|B~1ynQ^pxPz9;FPJ&%@uwUxE{k!UZTI<>B(qpW@`1so{`wB=~5l4C+1e>4s4t>sk**rq^zc)p{90nZe{)ChEwv!Wymxn>h)Aj zZTjp;4^`FG&d`{K?hy@@CrbT_Os=l2uCGi~m)FA~ zsGgM=RX4n5Vr0a~;)>xXRFoGF9$Yefs5vYjHfUsi7IH#ytUL=ISzJ1*qBJ(VA};?y zfzQi|$7aJLVuMZ?6B`i;R2kP4NiK40>k_%Ms}s56n2a#6PR>1}dUnsqK~pMgCr+(K zD>hs%tFEnUoIJ&ZNyepKlx0Lvn;7)Z=1cUAoKn{~bz<$IiQFlb)5Xo3(pDhyCAC#` z_4N|eBHu72x1r{&>YfqJOyyK5!ilrJ%wz<)CgU41y{@4qQ8S}Dx7r3M&ectv2rP9= zyOqZJhRWemt7cU9tg4Enk0P3M?s5HdYo<*<_SiGZDrc2e*G^7M$vxzd+-`}wy4V&9m}=Ke8Uq_*ek}>aSj6-5Q3Fb96V>&#l~ae*R8O5asIF1_kX&>QepV`T3k!~# zP?HdUCaNb_*Jt=OlFo9doYwx$kyF3Rz|Hr3wd_rlMrB%cLqnzH(JO@Sx2rHSy=h(> zkgHj!(tPF)=%3p=zd#d{&5WnbUo~DZPR617?rg@8+WmfI+i8r)Ov~y|lcfLlsdRq* z(nFZ^BMdu3B4f=L<<~nqc)#9xfb&fE1Y_5PQ?cWc(A$gsj| zz5~CvZ2w-5hPVy^A+?|? zchuool#H&`p;m~R+*4-ONWB=9+dtR#8RLATurs5kKG9e?HH-Fhy=)pw14d=JJ|v$b zswe3vA$+s>3%Oi}YJ)1LPMuI$bw&^A4I2`<>NMh#+DUcC1sy!#5SOUSUq}L@Yh@U? zX$!+`-xg>3Z3`ul&PAS@kB|4hySU>&dB>4uk)eYI9h=)@^aQE#jk(A4EbN(gRKYQg z<}m-<{JuT&dL8Cr?+W>2jAmT^%VHVPeO!fNJF31Tt;|(HnNwBf1Ye)}ZLF0&Fd#cxB##uP&q{Sm>bFZT zere7n9Ts$)-zna-o#(!xlHEvm`RE#1-SkxiUw+X1oTd)#M{DYXMNn-23HEH-@YWnNCJ4M)l>if%XQf6nIEf}HssnmV?>z!O!yqpaM0 zl*`b2k_!8IYqs(WDDU(R^DI`q`dhBLU9JDQ^wW8pmrjLw4>o z!JIa+t;=Y1J3#+)=f|Ya@27r|E$sT^HgR61X7W>gwJ>g(8tKU4!lU z&Cxa8%4YMa&LAwb=ik=^+vKtRDVoWj?&xZ{XWwJ?nlQh;WzTPp-@HG+AkzST`lWuG zr@qKDx1N#64*vO}8RyHt=lpbgepmncpZeEp%q+C$&s1l-{Fl3Sp=rCE9{YI}LQbpv zGAnqO2^+ItRbKVJN%_J3^UkC6RHT+4mL&YjA=xKMpvOk*F3)Uf^V>u#yE z2^&>oiEEdNto-j(pGjZhY^b(N(^M|z^ zcHVF0?$d9VZ{Nx z&sZxzE7Ttc7<;roSNVBXelLyBtp3iFzu(F~zZvrC$M>wfzF*<#ZyTp-N0;qYAQE{X zs~|E3A}jx|(0t}*_+`44kB8d5G^3oBSoxt@{jTMDppn-KsrIk3^1q-xWoSQ+ zHRhOlsq$V!7Kxlj{gj{NtB>T0c%EtaB9TM%TGM{~Z0AmKsc3q_ zCpB8vMCf+1_htUiiR^}>^lnaM_w<3?`?Y+lo@G|gp^(Uln0s1~NaPJGpKIk0#@U?6 z-Z)C{=0v)t5A2@)SgEGF)*knOL{4O19Hn=2{5yj*)4d#TgpdJ?MZfxgiM7*=cSWMb zrt5@z+nuFWK2PIOHq&3o_bZl55Sh)4Z@pbf*Yy1MDE*Za$xR>Fy@MqV+k=~aSk4_Q zyj|olU%trS(|mQqk+(a<$ajx8xk4*(ndNisahd&ICtTCbwa2FZ*!>*SBiI9cln`jv~(s@Bx-z6ySp`*VR|terowG zgtA|5`5yy(jOC97xOdO6Ut~>yPq6ZD2ly1rKM(L)%X8Xgo=8}(^`6^Vmg~|HZgVZq z3-AjqFA8w)9%jFYE>z)mxsl&LlKGS{5?O5Zlm_IlxBT<~zsYj_86j@^*G04(UHjtB zEw%jGfc$-y-xS~v8s4_PEVuH%56G{y^1=S^FIN8Xfc$e-KG>7IY~^1K$gj2X!It|S zE3fMexqV>ea|vbtQ!Brtv_ssy`@sDp<%F{Tos~Z%Am72Xzxze{2lx(_4-fDzmQM=s zy(~`#_NRt~vj3g% zgD@U*>Fy|@kWJ4X!n5h=Zuwjr>So?p^!EzU(?5it9Kz2H;dh4cdqVibA^gP<{!Iu! zPHy?K`R9xfeq#v#V+j8^gdZgLui4T)B7`3k!iz)r2_bxZ2%j!o<6)`PSKZ89ynNpl zBL8>@e>#MJ5W=G&<+33}ejm9N?}q!Vn~b&c>Vj~!|6|doo0;>M?^A?l^K+GzUn=FJ z+XC+^a*5?dlD=+c&Ro9#Wcgal4>xBckq<2IBHy~XJHUNqYC!GDv)suKw|snnpKbX< z%U!xRJ3aDE{m)unZh4h=I(=`r)yvOC4{NMRkT1>8pHNdbs?J+x zD4tS(hPg_-=)0=Ck6c&LkT5yZi~9MC6=SD|W~em3P*#r@*H0chux9e`#%WqGz0ER3 zDTsg+|+OM@qt zVO~D$3(a7b@af|%r7StdE|rYM%12dXXzslknunI2FtE6^qN1U3LPZI(qDz>2mJZ6( z|9b0xef7US`rk47UqAgXKi~Xsgz^i_exdolm-*jZmv64gHy7m_CHdys0&`V?(NJKn zEil&>m}?8nwFTzd0&{JFxwgPuTWGE=G}jiIYYWY_h348qb8Vryw$NN#Xs#_Z*Y+~k z_A=M@GS~Jp*Y+~k_A*!XG8%fBYkQe%dzou{o2z;o4ZY2^z0Fm)XGqv|Vb5)CCI3$*zd+&eZy)wOAb+zG8~+ajF;FP&|rE??EzAU$Eo zkdd)b6{Cs=md3Q{Q%~5sU640&YTeAC)rpKX@v$0}8m115&GOdD+lI#YLU?|D+`P0f zvP$0E$S)XVUheQvtX!IozPe(*Ue?&>=f$flr`v`^&ZKK?L@G~0*7{adO*x}NU#H3H z<}GUMZQcsT^vy3ET+<+LB2*8ZS~sC`YOFlNDA%xw36%{E)%A(+^j)8jR^7L(@{DTj zY(kWl&nO=`|7JCNgnJAq&wcG@PYeM}595AoTOscQe)_k~wPOE>c$_AF4P*IhrH-#^8 zbxcV^-Bfu`C_hhPa!{kZhf$h7Kd zRnupi^k+CrMWMz{!KgaZ2bwo|ywrmsKPcaXxii_wSzL|pM z!>Y9WH3y!oDST7k z{se(FwUO9}5fw5Xsi@Yxn&a=%gTJ+LhpDybW^ZF7Z{r=?_V zpAnfRuOQS_1!Vf2SYMN<_DZv=ro5&ma>Br$RwQO63TovQG|{K(Wc)Oty57d-$O=C; zjDXj!d&Oi*RsumT%rDUQ*W~rEyb5_2th|rB3MIKMPmhKn3OrONyHqE*tyO|Pu4oE9RjX*g@71UzeoIdjT~!Jyt1BYPWRV~7!UhJ;<<+hU|) zOV|ZAg@VE29COX|Gbfi1>od{wPIhyQu<@h{J6Ra+c~W!ft5u(esWtvk$#m)1^fPq& zVk1k28e7YU<>%>TdMrg5Fg8P6HJ4{dXR4M`_u}1^eXrOcr&`@2Nfo3?_QY_Bmt5u* znF)$>@(0J^^4=4tWXXgr9u@T+ZY4AH*{JeW8h2+`sebYGsa!UFDpcqtS~1nU3uwi( z`^Y~gHm1B{P)T__HlkwCsIe6_GsHi~RL_`RQB^a2irjEiC1y!xM6{rH8_|l|I`hs^ zdA2L`4%FVBRJhw0QRDY){Yq+U5`(77SR%9W%fpR?%1bLzkQZyHs+_JPPK=;Jx|94~ z-oR;8^|a~QE4FQ0GWv)7K5lsHE=YG3K~)9$BLjmz^CF}-@)J8<>y>}ZP`@J{R40SF zS++kGnV?S7?WOw-c3sD~Yt2o4xFh-)?^K5jt*j3-J1{$NcB2a8qb=+WBrpCzx2=!8 zv5v^tVPk%upzC5a8RgKX!);S8SrV~h#;|*Rai*IULGM1Ym)xTam&QhK*ZYl>`}4{~ zV|}$0yIPdrPrNRDXQOr#1FNT0&ZvzyXqw)(RUnYu&S5A|DpXF!!O2kv!%lo*Z z_oL61AA{Wsq;mz#DbyaYeprl=-g2?BaxsUnVpryg|O7m3*mL@=C9HiGNG;;42Y- z1mFJu!Mb$JZGSf42kYpQwr7~M;?>iBu%_Os3BM-rgBA6%zm8yk#9*uS*q=Z6!Fme4 zTy3p6R?XI0qm7w$(AE~1YT5<`)=S&5AL`vcW6aM@{Lsq_^Sr5yv_~?3MBs<&E$Cfuy4>d5qu$aHN@q^V^|EGVdV@oyZxT0;}qHU!c-1v9owm)v$D*Mg- z$ij+<8P<7ypc{k9J$_$rVn}{rLMHI5Wtu_mbTj6N+yKZ7ML279a<3X0?dcE(cjlZa zH#dVGFw+=zN+WHycN_nGlLUF8vjlD&a?IfBNj0_AC(NvMJxylkgh7|zKLz?L-&33D zuq3BCD{_p6>`xmT5+x1t`y^B3hTO}M>xu>i24XU%)&9SBrkR=%CC===8FP)^u+xnc zT#@Qfq&#qYNo~euv6{>&sD9Pvhj_GuE+1(oIh|ekeY{iYD(xiFHWl`@ z)1aAYYK{Y`nhB$Z3Yk4Jd$rXwBjvF&`8h0^ACT#cx(d1FPNx*n`;5slqv73wOqg9O zBP%mGroZT+;iwZ4ULi=pNm_;0i)o&pKUy46Sl|u+W|*s|d%tl~G12~LkKX4yCZTM8 z$j99KiwE1b+kBazB@(Gb$C;vs^i8nN`S-#Tb9+FWF=%E-gx)a-OQFnAlKP;r)J$Od40s zs;rRPu~{_<^F-G!YcVT}XA6-Zax|M=USjxJ;CA^(8~KOq^I=&o961~E&xG(7!RJ8! zBg=Ii*u~)bclUHt{VDl4JM}N!>8A26@^QQ;zZ~4X|DgN|@M_3k z39f%_Qa6>SJ^DlZx+z~IAD7>=z$t%02zT#G=xJT^;`A(r{8iw$fYZ)RW{8@1N=Vfr_t5c3#ESvg)aqGQDrtipkapm%*zaOld@+0NrxO*=`xh_3&{9x#3 zTnz`m7V;;9GajnJuY>%V;6Ddn1kU^}0cW}23{LqwL-;+GYkqqo-A5tMa$g0`@_hxI z<@*nCmhZ>ljGwQ;S&rWOI9~bw0(Qo7w9U#4fea=>j=shLY{W^ z1*e@wA$+Li8V~tMcMRlde-$|EMJ+h%#SC!9xxUAwo963Q`MCI*4^I2924{YM4o>-- zLin#O*Zgwa^#J6V-&erd-nN3X-7B*1!)U&KjeMOM!Y>TrABOOKb`Yhq1@&JT!WW0| zr6K(J9kc6yFNC`#=0STdu<0cAcsKCJ!S($b-Bb_t_XDT?IQSECjkA9w_zLjTz*mCTfIkU7+w#MO{Tcjx$Ug;s z8TixSzXg8={Ey(Y=P_{F^DOvZpyvhfXTjeBr=MHF>F4&l%Ehv&|JfdH2Tpl?FG)9* zUnL*s{{z4&eeLwKka?X|Sk>Gy= zKL(ufIRu>j^)PVSIR>0@cnUb>CxJ5#>%l2M7o2f&F*xJ!T5!hU4dB#&7dZ7V17{pQ z1v?GX$LeDYIPT zu$O#XT%8Je#^H4E)sUYH{x|RxIOFhIaK_;c;I#7&aK_>9z$yO#IOFgMaLPXi&Nz7; zoN@S1aK_o<-oa=UQ<3=SIsl4tvASrI2SFJ_gP>d=C6?(DMd3Q~yce)ISBBao7OPI6N1e<(>p* zxnEWf-??>g450s;ETj2=g$+tDL(<6aaapZ`8nW>lMBHahgX3!4zB~J z{yV{`|3PrZ;RL;EcnMz^T7oS8<|jTE5iZ1)OpCBXGvyA>b_cd~lX~vE>?vFUrT2 zZwcfXhbMtE4$lT>99{@cdoBZ~J^FhBx~U)NpI=z6aoATr&d%RJo^iMgoN>4coN@RH zIOFhraK_NefybVr!-Up|DKCxWm zupjJnKYgp^$T-|XeuqIf<&4Ab;Ecng!5N1Gz^@Tq&Od{|Y3Fco#^FeC%AW?#I6NJk z^0UAhCl`P-4lf6199|7h{kMZt|NY>M!$-jxhkpTQxxWO?a&NU<7R+hcAFL4&MQ19IgYWo$J9FhhKwJzLWhSHT4_ga5r$u z=Ylg%4hLr(9t+MmJRY3-e+EwdS`OtEW!{cD*SCD5M?qYw)PRo~ZcmO!#@Gx-3VP9~@VSjMi z83$(^mVr}#EI8wEA~@yi!5JrWz!``0!5N2_fm8plz^VUkaK_<7;EcnS;4JsQfwSEI zVY$ZPYbf7!kY^lz4bC{+|3JA|HZ6C?VGnTHQwUCb`hwFx$6Ky(*k3-bJuHPh<8VAU z<8V4S7#^J@_jKfR8Y3H@zjKdqiDSrnzhF*%PM1x~mvI=)RqAoZ;l8;B8+n%d!Qd?S-j-_|zAhhEzWpK3I4lEa9M*v|4$lIo zJuTq0=VEaB=Q7JR4hP7`*?B$W8Haa+GY*%7GY+2tXB@r?&NzG%oOXTy&N%!8obum* zGY&f+6fv8YJLUHRXPo4MKPJ~W|Kx!)4ts-B|4?x19|O)ftOREqP6cPV&je?=pAUW| z?4M`3#^)R03n9<=TmsJcTn^6odVsf>Zx> z;M9KyIOFzSaK`O2aK^(^;Eabg;4H^iE!VhRD<4-M--0~j_H%H??Os2Yi)GVzVB8)A zPCJhTr=9uW^jlxc+l&4p`8YdckZ0VE0B3$r24~!!4$io31ZUhfgEMZE;I#iraK`O5 z;FP}!oN>DpobnHYKMMb>1ZUj72+p{D4V?Nv0)G_xzXNC7Zr@#mWYc(H-0lI+csLN8 z@o*S8%Q4S#joUZn({F1n*SH-BJ3oXxv z{^8(^+mpZd=7z~iy+VV{3SU3a1S`+^G$Hde-gsm z9Vtf0rsYEUT|@XmA^eCC-YcvT3W7Q$zS@bg1>Dugcz;WvQK5#PDEy$PKD z{A~!oKZGw2;ZKL~=R^3~5dMA$|2%|$7s5LqrP0$ievSrTC+D4ijs<7CQEa)^i=mJo z3HcAePl0?Kd=lhu13w4+L+}OQv~w{y?YzNqwX+0z?t(n+{3GOl3i-z%Pdi@${}A%) zz-i}taN7B;Z$ z@JB-UKP=aA!o{$sZ=M{;rvAKCKF&Y#S7pqmocBRx;GaN#EcnOZGr>OvpAY^S_+{X< z=U3nyA3g}q@!?aJYktpx{ud#CK6s~mIgm~B%klOx;Oy51Sgvu^O+LD2NVgdHVRG#J zSqeS^d<^uT2R;t+)ISlN`p*C#2|bM=`X2|UpI3pi+}D6p{>Q0B1Q41OFWQtHFN@z6hLtSOQMJ-3(6o zJ45(AmaE@JBi%jr-%Ac;Q~ztd(>&|e1)TM6Z}1T!=kj%s zmHD&{-eREU;gNn+0>pf@^Si$LiESLSzfci>7OQWme;l5EU(AGSzgbBe+fHZ z2j2kRwYMC|rvCYtd|bW`1-}72AAAXTKkysD2Y@rbKLcL``7z*>uL$91g0nte0M7b& z2{`NH)!>ZJ8^EuCowtJD3Vt^@?SC4a`nT&N7t5yp|CM~4|GR?U1U?-6X7IV-)N>g) z^{fP^o_D~%g8ud3%P>Lk|2a7G`!8_Hx9=xL$fkZK z-`?_Ie!D`R`8^Dr`ISFpXg1ZqSU%2g1Hi8VF9BzM$Ai<(25{zg7C7b458?AH*Zdv< zd#;8&^LrmS^Sd0J`F#rf8t8u$oOXT=&V2m~obv7Ur779kl%wUre07C9^K}?F^VJ)i z`5FMue4PN!`db^quMFY858+Q(uKDUFA2%*~2At!T=fF8GdL8;XE_xgC)c*lE^?wFF zM(lBM{%wf<_WE*>Y+7C%7xe{a`3?eSJe&;9aZwBS7m|jv=N9m5!T$ixbeDrO-4)=J ze>Q|aZ@HG&iAeWt$TJStgEJ1>9VZvd7Hm(p2WK4a0Zu!6f>Zuf@arTU=eNn=mx0d$ z{~G*P;NO5h4*o6pE8yRO{|lVpM-RC^d$t@)c>@< zH#o<2$Ad4CYg~B^1?RY~6r6UR2+n++3QqZnA$$fn?N5T!{|mtxS2ut&uKoZ%2l;*2 za`k67`RF;_9tUT;`ZPG(?dPGN?e=Ssr~bFVsec{#7_q~Z%NHT~zk$5!ck(&MYcAUU zPWukvN6C37zlY@-KeRs%&TB;obCT2@Gp?=ec){WSAa9!)!1l6BhU7{J2>qe08aU-;B5bAfiwP-;B5bY z4$gFM1!uec4EQ&Zbewzy{w?@-;IwD=ViA%}{kBm)F5Y6`w5J@LJJD;I#8ZaOUe&aLP{%;WNN#|7GCx{~eaM7aP0D$Fu6JA=!fI_629T z3<764o(#@*y9N9UNypiLD>&PSC&1Z0yaUd5emywbw~m8NwoJa*o*V$q_N^B<^Lsov z+qcuess9}CNV{}?9|EWTmEiQ}GvJh86T)A$yuD0Ny!_ovvvrXFDL);YerN=z{5c`K*>d&6$?|dWb_L|=hugr}ZafaobXS4X z&Nbkae=UT+Wx3jU3hew0^0c$h5D}71{kC2{E?*PDnQk38?M#4EeohE)vRv&v73p3M zdD?jwIOFO;aK_bR;Ea>kz}X+Y3%&&Qd<4$^=yP!9cOy9c(_yG6l`R;bJB9EA!0Cs+ z;EbzrA$+Fg>gR6qasAY};Os|Qz{iNZi-$|0pZ(O8;Os}PgC3^)OK_%pJ2?Bt-$Oss zeE{;R-`V*HIQyxU;OwVXhv@GR7p1ZV%PR`b@;wxs{nXFEKNo$@&eOs9ob+69#_et3 zjJJouDgPI6*6UWwgYob&ILqZraF$EE65}4@AC^mJ%Y*u(;MBhtIO8qXa`iv;9}LcT z8wF1PRDiR*W`eW4ZUkp}Jpj(~`U^PyzX6=~?4pb3WYc_6{s3^6S3k>x{wxANOmw-p z8Vb(x`Wf`opJO4f^~kjk72woA37q9MJw$&aILqrcaQf%>;4H7Fz*$~jfU~?h4U^2s zrhfiXKF&Y8fNual1iT%_SI2@S9cGruQ+Gry;SQ+{#?pACK$?70}6 z{pMBR>^H9mXMElQ&ga^9gVWBZ!Kvq4aQbt*QZZUKEw3f=ape^Sr$6@qXSxT1)1TeJ zDSu=L9{^5&4g;q@$AHtHr-9QC=Y{aAz}XHw1kQecO$dM6@?g910XXaRXW*>Y-$Fmz zjrL_yNU~{pv0iU)c`)5B;7oUKaJE+mK|j+S3(j(^0%y6O1yJ`-0QXq2QN`K4(ug z_@&^}!CCH&;FLcngg0BRzEG}lej5VLc5(_h+sT>Wv}XZ$4%*L$z-iA)aQgEZaLTU< z;jdb*am9XZ9pqWRz5!>yw%tfkAe;J={aO^9{nWnTw6hmD<*UIdKOLNYXauMHIU&5+ za`i(-I}dsK;bw5QGtYys7hNt+J_M&d8^CG*x8RiTI7*btrhX>h$#S)y?fj1*Py0uM zXSDO+OGKBme=>MRI}c8KW`Z+cbHFLz9Kx>xr~P+h_*Mn34x8P%-f4k9gAX`xXPT=f!cDLN+%h|avINR-mz}ape0sZV3 z#)7k4s=ybCy)NCez&{1Q8T@nbN5QH8FW`$H|2J^TzY@a#Zn^r0_4gCVGk)4@VaTTb zXFIktINPy3!Pze5g451p!6{!2&iw{a=7z3Eo{h71`9!?3eSv*$<8fXMWEFr~PxlncwrlDW44C3oY0Dj+2k` z+YOLsejfs-{*~ag=NWLyuL6D#e-?NL zj6<5hJA(floc+kH;LPtwA$&LOv}9BJsb@d%C34Q?t2;RRqrQq5W`MKbnG5}FpD%(u^Cdmg*)JTdjfiYozU&tUfm8o*aOxikPWe+p_yo(fTr~7t{G17Smg5EBS3`aQ_+s!y z;MagJ0jHf0fK&c$aP|uwwDQZQeq+C|BX}p&$KAoV13wP@TG8eFPzFvr$AZ)U*V9)yMnV_JrcY#%4Ib8H_&qyILrM)@UJ0%4LI|A6FBc%9|WhJtHHO2ot?B(luh%y zUOq0rF>t0^4$g8J4Nm!SA$+3cS}vy{-3G|BT{XgZMoW00efD7 zJni`uoc-E2;7g#VgJx1T_4AGLaem$&oObR3&V20yPWgjEcp*6L|0y`@<7CU#58dQ5 zM?SjMg0nwr1ZRJD9`v)nyAbl!zW|*2uLK_>b~wLXAEN(P;A*>*zXN(SUB~YN=Y7`w z;JnXT4*ks625^>3js}x#TJ9{zeZkqE#=zO1R)JH0EjaZzfK&eL5PpH>TJG#mFM~Ye z=a=B@Pwxb0e|j%C`^RPAwDV`$kG)6QAo^#3{Fly3>)^DS5Zvp>BK^7Q|`;H%vp<~!&T?4*PWu;wGrzw8r~J(! z{5O_sezj?L`TZZrGr!M+uZR4e6XZZP^$*j{1*e?{gH!&f5Z=r3_M%^#B4_6y$kWbo z;4GKZ!M}!{v%zW4h2XS51y1=ZLin|ox0f`>Bi-8}Py1g2XZ&=kl8a?iKeK%(1ZVqD z0=`4LwBJU6^S-za{02?Kwm)ZqGrzwL;jdb*`PGnddftTm?cg7QGu?lIFM)i!iE<#D z`r$_TIQ^Z#Y3HusEXTdTDSto+&jV+96@jzA7zWP%Vk9`*{|d|1Z{6hM#wU}&IewT1 z&hg1i=syqsIT!NO-vUnk^TEeJ&s8D%uLI}!WC=Li^Dn^Z|46kYCR+#ju)I2gQ-0?V zzK7-N&k6Ezaq?rxvmEolS&lyeXE_c6XE}}rXMV?n(?5&BnXg}g(+>}TbA0tS_>QRW zJ57?z%clNhdw5_7?+1R9T;u#UJcN%2XM0r-emV4<3r_hfz$yPL@STva--Pf#f&U!o z{w0LJ34RCUTfuJy|0INe1I}{XYqDG{oBE$|5(B4vIXKIGG&tqQh46`%Yy6Luk1NLp z$TR-uf;0Y8;Eew(z?rWb!FNV^-3PuN_Phqp`trWzYJWHRxc2Z9aJE+)z}X(QpCT8_ zrv7JpxV_~;{awJRe{XQMhX;k|KLniheJnW3u?n2!eik_E`_162?<>K-kvzL{e?Nq8 zU!&gf{KN6XAtC$(aMs7k;JcvQ6X1-8%fO?Mza9M7Vwbc3ad7%=6*&F22AuM*h48m5 z*LcW7x}QOw^`*n8=8&oom1;|5^xt%W}2zB-r^G)Ft35h&b$ZvX5dN6uYUf0x`!~qb&JV$< ze*-w}`4*h=9j8iSvIYIWljUlU4q=?%egt{i(;J-ni@<4544m?1A$*kOYL9m5&YmjB z)1KMjDafA>{%i0nzCwU-wjUxKMl@)@LO=ocdiqqvT0ngymkhs{GK6vKg%@^IUYCy@~juf zfpa`C6rAIM6Tq3Tlff^Qw4MKN24}nRJMblt{{uMNjR(Omh5QO|`t50O%0Cyv-vOt8 zz67U#+D{iFWYhAZe|7+;e+~g(FV{H#^arP%ad76V44m?#L-?tdYdmls`wYl4zjMHu z-;2PR-%G)n->bn{k8TF1{Y$}_-+RF+|4;~j%yP}|iSYB^AkX}M0nYf`2)+b*I-e;A zvT3<9K6eJEon671ul>O(e@F=L2TuEc3eNHx1J3d~4V>lG2+r~FMIrneaN2(pIP-fu zIOXpO;rCmv<#>dATzy#qdHUfwaQfj5aQfk0aQfj3aQb1pdND#aEqC&LLiiCOybn10 z@&1-;e!I!XjZX%HbNnz2e1yn5|BSX=?d166RLE0*6*%>u4n79@6CwI<184dE9-Q&; z6!@pm{{=Y5Azd3pNH)zE#|b^aFOzf54~5_yC-evBIOIg|-7p@Q3VsFj&jM$DF9&B_ zJq}L!Rp9i`8gR)$@&rnXMNclocZblzFu@W|CfQY zT|E(e3FIrl*{)6mryuIT>9+(p<>!R(OTg)$o55-S@4#vQAHZqivpmtVf%)V~It_3LfR)z6Ic55O7cpMkR;eGC1pM;*=*#j*wU?+8x)yMd39>s-F} zvt0c~{Re@w9^C@Ydh}Ot)}xQWS&#NUTdnuX>stAC_8bb%@ks$V$0q~8e-1rW;MCs$ zPW|VCUk5!GgH!*_;A{t$g0nt;5yIWTRsGL;-BFz`n{w*eIfU|6(V`k~`FA|#vo zne}&naHiV>oOT`sPWj#;{5Z>lb`FC)?Hmiv@~Q%7d7S~y@@fEQd7TeVKg7Ho0>ZjiZS$?>D zYu25-)1&g|gWJc&zC90Gd+J0+H!WY$Oh*T+4&@Tm*S7N2mW1aO&4OrJJT( zBOj;#28FT(_21&*HumdSOSho?_juTFeT3-rKWuqW|6brtkndr+>eqbjXZ>cwp-sAd zAkTD*EDxp|wOq@wMLy2X0?5;zlP!1lylRgt!Rcp~yQbmv*IW6ZJuW_#v%YMpokh@3 zJ)Eu71@2|`f;0mJZsqY4$AjJyRWi4fja+J9v852KZXbBi3F$t)DJCdh)peo@aScfRDF)e1I>sd|`m+*}_~J;N_OT z8sN(;|0clKTHeDp9M1kCThaf&)~qJBjVcJQ1eBkXg;MdO2w8}qpf-!`1RChYQsOpg z!8M6XDMdJIXM;nWU9;YV1o5*}l%}PJR?4BrAO!>$6seaW^$?*Rf~cw>A#u%(94gU6 zg^=LDjAv%EnR-)49sAJkd|>K34d~VZxUbo*E+j zy267ag#WAX)a!)r=jTk~$-Y7OI|@(n2H}Fjmrqjrs|sI#m++ekUmhd8gP&v3t=ohT zC_Ggq+}HRN;Y$h+cmwsD!q=y%{r&tt2z5Uqyf=d5JWLV{AF++ODc>rC^*ypxsd;wI zGJSj2H_S21w+yq~Xc$evEWMrY$y-i3Rj|FrM8mfoe<+`s>FYZ*?Ns~;*U9Ba(xuFS zyzBJ4^*O6tv$t9nJ!`^m42@(;xm<1_lbbP2&qW1v+v~Vvb~<&e{JvfBPk2^6ojGA! zll@k$R<5j@c5^bvTpzYWt1F48!b67AL8s~77q8?~M6|0{6Vb1ehFIPBPiKf-? zEzh5>Gc@5$_$ABptU2+@H<}X(MhmoHsETjiIiqqhEe{MgESz!bw)i(I4IgG!#hsdh z>28>g>)Ynx{PAuGtTM?YyILCetSQ?t-}77u_Fl_LSTCddAn}*w3cr4u|1nMi#>-h~ zE$+7W~t@;MbUsdsZyC>><`}`~kGZ63zd6xNet!p~>FP zKeG!yetThw>Ys;et)B!8x1hY-LXFBY+Z+7*li&%du*G*h`pojRn3Z3sw(=uc>_1#m zWIoCF!gGM3K5yHgM&(odxNcE+yByxx4>k0u`2q7qPYC)Nw=K>5aY2g|;p=|U`F{x< z_^smK-ATrgVRSJTIsWq#oiX-QV%7W4@4TlL>M_uu9N)DrVE;Sj#eAB;z9BV%m=&xY~$6J&9p lgKL52KMWXza7S7FfuP%++i&UoaevZ^zjBFMj;foQ{~yo`OcDS9 literal 0 HcmV?d00001 diff --git a/express-server/node_modules/ursa-optional/build/Release/ursaNative.node b/express-server/node_modules/ursa-optional/build/Release/ursaNative.node new file mode 100644 index 0000000000000000000000000000000000000000..0e9e18ae905d9d44cc4eb3b86473c4f706013d90 GIT binary patch literal 73184 zcmd44d0>=9@;*M?5rv70ii$ESDxzW%2$v!W5HgVjBH>cR5R!pJLK2e+1VxM{QO0p3 zx~O>LjjpbE;~fw=JXV(Vz||G-Sb9VatGj|1^Lw7^erI|@#`UxN{o^+p-mdEE>guPe ztNZQuo#e`_+;JT{bZ|MJPOfuZq%y{6PKK#id1Oo`!!^v+&6VLg&eca`yBL}FE-OCL zT<7X?d4xf2UGcN>6CrW+NWr;!x@mrjxjOASg3WfGzw3I>-#t=ru6vA`&NWGkxjN&@ zpG~H|?X{ngbFP%-C;v--3Cnxl7V>~=FB*i8b9LICk9M^4_kNO%;3U&uB3x#5(t^&_ z3`fS+3stPno-oDL`PuUONA=oT_;hB0`60J5F1g^!LN+Wn81La^-h)d0a^u-2qH5m*>!oeq9?5JK@Afk{|5+ zdjGzi#r4$3PceRc_?e5JGW_r}4?pGjnU9|;{9KBkYW&pVX90frS%{xS__+)}m*eLO z{4BxGmH2T!SD|njeqT~Q~-;du8JNlFFy7b(&qSL1bHJtF#_{=Y!RIa>brB4=ZJ%8|y zx>v&sZaX4l+gnp!Tm0IwmrQ@?yPf@>J%8%awQt-u^|-4Ke*de#w)Wio+R87!|7h@z zK>7MRMpXA2e%rp*>K8))?0Msit0(>QYggV=UkuK^^5xU=Rt)+2?Zc-I-tpBPV~>1r z&_6qj>iN$r7T0gvkUDPQ(6mnn?>PCSD*_kq8&$dHjD@Y6tJdG~War%EgD(2h&d+M| z7yYrcudy&U!Qy1(EI=V;c?4Cf4<<6YX+7bQTy58 z9WQ-;)8cy{JoVpGmTzBN*O0eo+ojX{EJrYBE_B1B2^Wp^K<$U+pfSGaz z>^ZC*{#gm|IT-W1J^AtkW#QzJ4?1#@i?fCulp6%Ot%MtDKT^MhB@!2=Q zcuNz+TX~Q6^$bg3rz?T{lmzj1Ujp1FLH~*E;BZ+2+)@+h&q)vu5$J9YpG^tm^Ap(l zdV>5=k|2K0OyIAz3HrS~!FV6Vg5RF~=O>tVT@%=!mLNV)Mq+AD|EdJ`j7VVrQ^-s0 z=^1oL`}~&@#HTxf{ILn*d@1a2FE33_U}tp#zsyU}?@YDxe4Td zO3-h80^EL15TCUPaJVeNI(2h`eh*5Z=avNV|7(KrmIMFx{Pj$NcwUyE-wzY?+ZFb= zr@t(Lp2HHv`H%$hd|iV1m4*AA!(4~B>L==CcD%`Hw_vkQepP{H6dQhj%xm&n^5glp zAs$WyKYyL(&oJ`)jsBHJ-qAnK=%2+ziqBX2;yM-hh@SPD!Tmcw-4Q43*TYRRK1X8w z{Cwdy_M6Rn5^&__0pKR`k7)WCeQ}+O_#wa9D1H`r@so{tL4NXNO<#JPzP>E`2lP8Z z(;owZX?+TvxzO;}#O;f~i=UUwcvs)7=~m#v&lg6| zN(0Qhn(Zoc^t`GW7aRFQ4L{>W&A-dcm-(n?zxf9LTa2Fb&AiLFUo$>H9P?9+co4ss zdHR56yC#}=NHOtXrjhIK#_w(YxZB8YX%j!^yR|(nbz1RrW+L5c^whtu`D0DLt+4Y@ zY$`W>?hy{u%I78HuN}r;P%EEZCZ1QDd3~$lZ#`7^yOKBQ_|zGE&M^2lH)wtsc=1yv z>-$lz7Spfhx?IPaep5_-bLP=v6L0y~Ye^^G?l9xsbA#qTh;j1M!|+#{#N)_w-nZwk z#bQry*OoT++-$~Gf34QL!HnxktasG2@-fZ-(eU3haqG(0diW4V_R~F{ZL=5tYXzCs!Ah`D=0t(h9S(vc{%mE%<+_E>)|8Ekh>GzQkAT zPfIB%uUwez^XF7xxUhd*nXkMg3qV{rVLVOFs?+@RsYT_rzG(B*RBus5Nx83}xU$NZ znl`4|SLF9;R#yImg2G{CMqg@**H=`fJ7Z01q3JmbZh!}h=M@&0&MTZ#R94PD2Uk>< z_)=4}{Iu$#s?@Y;zM^?!iptApLpE#DcmkO^#AfDH%&E*NNC95dfabnROJ)f4;cNRN%4ITA5-ots{W16+r`jC(d4NI!rOkgV@;eKV9(eTL87EQ zU&31d78R5m(iVqvkrTAUBp4b7>kEJrA%rXVKA z)K*tx?r8AEmLa2S=gjd{51Qaxh+wkhv*t%fZe#|JE%Fy-Q6@dNvbd-`$BsRO%6#Aa z;;Kc`{{qKS6FX^>E2T-+{3`#VsO#fGeoU%_xnr&qc|!{P)nyfPQ&VB!xa!LJQ~Yy= z#S7+-FQ)%F0xc`fm-&X?hiBCl`>L2C(zB|oE2|kRQS%Fpc7%`#bf^2&!IMj?D;Gu^ z$2T)mH`*$0AdXXPcqvemQ-Rr8QSAE-2%Y(A5Fe83tC;IA{f!2rClt;ut4Nz&;X8^EUR#3O`23V*XJ+vaqL1#33-C33Zs}4zz7sxIDE3N&Ofb%1VqghD@lPKRX(m1%-}tvP3{H2-;2JSp)(arlxVG)cE`NLpSzXh9D=Hrz6)i@Nt17B4nx8j$jKI4^T(&Auo-E%vW>BE;?$fUCmpXEUf1#N z_L04%pPWzo%O>}qhE#f-_IH_a37UbzArR@yDxQC)qz>Q>_J`+_@l>&GB zDv3)}ALZK9N1;Kw)53B|Hb#ugN9xe5sriLta`L@dlM2U7o?ckC0Qd~`EvPCiE~_f_ zRb!p0!(bqqmVSU}VMS$eB~o5~do8#rDV$$fQd{mTbT)uc6J6Pc=U@jprW|{T_~e%o z-Rwk@Z(2%LO>t2b_k7k4D#3D+I#_RnCi~`BaaA?#DK|Kn-^ozac%ff(z(4i^mVjnpA+q01_Z^TPoP?g4&jrxUYhOtgRj zOlSSFR`-Iz*!508vcc}AaCiY0jUs<-wGVEmMXAGqI@ZowE)%1Dr9}(Mu%&Q7Jiw^b zG>l84ctX*9toyeA4%m7e7;C9R9M?yqPd14FE@s(*1CQ(GK&>W%9q*;B^5I(tF8+7mza0|$1y~e01v-`;(yk~J$D|nTy4#NZO@RH zJ#bCFZ~lL+DV>^XXP1{1|Bs3W8+^w4imMk@{r6Bida^41H$8*&sQy=TjGF(|8YZ*Y zT>76JMos?@95$GF?7t10Aya+TWpn<|Il-AvgHrTSMhp?&#*L|*uczsMJulLR8@&!b z|8LZ$4w+cxtI(hq)Rg`g$Y&V$lKg^#{GyT)+-v=}@TVI5|9egCXJ_V0XLA$1 zBRA{ufmu1aR2B>>bjh|(uYqRig>p0lC63v{;?5fNw$s@uI4-h7%HofphWqNOaGuEpI=_Ior_s%M>JVKOo6?R%%%(xZ%rR(u zpB!DDehjuuNE2d()^9Ow|D|gGO{u6c&gJ0|aHmRML87K`VP$oR@aCEwB2QEb zeRYnX=(EDvwQ~dyoL85$<1V_=u5yqnlmmWjH|y}EpuB8$jlZP$^wS5{R1O?MvdUk| zR-{u%7weirUkT12an3!vrUo~jc-r79^i`C&YH`Xlp~zphz&DV0magpFoY7+n(*~vv zjuvC3w1MfGJAHcLpn-$+ql|?A^3jcXJQP=AgBYJw>|^uoa!ev|$vm=2EPxvGILYNa zesQ@v{Qu@Z8r}iO6w0$DybBI``Hi>W30)W0jfU5&tPD@8I=k*PbnP)^c*54n^$=)& zIGPMoN7{edO?V>J(e;$6ci!`Mo(s+zODUIYm3jW{@SXS2SGVEM8l&acwBdV}I3 zo1@2}o7?cGZ`OKNwc*b<{4GX5A44zEqVn%Hi(hK-cUb)87C+g%r%pXKUs>{tE&1M- zyv=u6eDerWS|wThD=a<9+dV?@aqUuz-`nC}ZSg%8|2~V~-{PA`^HQ5)@$o1%`Wa^N zeNirA$>N(w=Thsn`28&Te2X8n_|q+ZmBpWB@tt=!SY2xI&$8sJEWZ7|d7Z_-*OITd z_+=Jgo3Qvu+|f_H#jlQXkt-}dUU`Uqnk_zF!H9lV zSbV%<5dEyQ_}4|b$nzE-ufRk<`#!iov$Ui|!`XBF3j}*v1QA+xs{GA>tkbjbt^gq*gdZa-9$x_n) z%-ZRZ0{N#%N&i#2(<24)PnDAXr)sB13gq{flK!V|r$-9ppC%>!PyJ4h6v%hp2_j?Z zP7g0K-ZP}6|7qUokpkt2u#ZHeD$R8*r{m;ss9x0GtCnf#Qs+}GwkiSey`k&Q1 zJyIY)MN0agH9I|0AU{<~`k$7a9x0HYCMEsPrkx%skY6Ju{m+)29x0GNNJ{#jZ96?u zAb+rw^glaxdZa*px|H-kYNtmE`7_~sQssoi1m z3oLnM@h4mSJr;k8#ouS~r&@fM+0QWkr&;_Yi$C4sCtLgrEPii`f1$42bVt(MnuR?=|AZlz_8^@s^mn9tl6DFG6=^r=J^R5p`7_eodWClg{WsFwa)q}D zy_Gb#RN)q(-z3c~Q+Tz|>qv8}6kaLxi=??l3O5V=6lrda!u3KwO8O|$RYKoKnp>Xm zETL~F&8<#2U+9}ibBhzs5c)dO+}eawgua?Iw=`jo(3g?smL;4lbTw&iRl+WzFCpER z^qyZi{@J8Gq<08?A!%+s!drx%MEXS1Ekd71`Xth;g&s|sx0vCTLXRNLEl0Rn=rq#Y zYJ}^B9zgn3(p5sANSa%V@GPN^AC;K42;Gr1w-jNI&_CS^ znp=r*ve4g=<`yFC68bCBXOZ6Xi};^3w+7)ILjR34w*=uWLT@F_tw6X%=r>7osSmFf zdL3yl@!^$1zet)(d$?KXr$}>257!I*DCwc3tAxIfG?(!3ETL~F&80h>FZ4~Mxnzek zguae6m+Eke&{vb@5*_vkeHm#kwc%u;t4VW-4ZDQCg!CxVdwv%Glg=Q$L+A@hb14mP z5qc8o(WG01K9BSm(yN6YO`1z)c%{%INOP$SHw&FcnoDH3Ug!a&vq@J8eIjWtiQ!p7 zA48f;VK`st!$@-p3}*=4oivxeaEj0!Npr~ydxZXJC1@^n;bft|Bh4i)>=ODb(i2JV z`APgwnoC-EhtPi`&7~~7Md+=hxrBvVgnpAWm#*+?q1Tb-k`-Pl^oyjqRE3*`eu^}g zsBpc|kCL87x=QH#NOMUF&l37}(p-wd`9j}BnoCePL+I;BbLk1E2z@naE;(V3(3g?s zQWH)Vx|%eXn6OLeOGp=z-t(jQpY$x!JA}TFbP?$-LQf(+n{H0f8t~t%1pE&0&M)1VIWT~46d;rk%#KN?Hp z?QDmovB%8Fj+p$+*SRXjXqXdbKcV!`aGBygZ9n^3yT6k+u*bVrjq-Nb;Qh;fe{U!( zG71l&LdV{=`szpC20gCYv%C!>hoS*g!k$AgjuXLG-ylURFWj=B%cY<@uz5X(<@)}0 zs00!epBbJ5i5Q(ZHFHYlVGo^Y1S=&-ua)OKddGbQ#{XE`a zcEtT$#=&R4gvy3}9TwER+5x59K&vVSY~H{|bvBZOG{^~TI6(Y@)E_82RAjSOdjm7q zctcmTeD7Y8wZ?s9)@t`@SuL5754^#wZ6)48+J@Re*mJ=* z*Y4|NT%eCquYrcit9L)72BSz%aJ*(@+|QhRJABd5lI#t1^9HX>@is;LU6evxqwbO0 zP#3&BS?ZghsFOd{{ap6J4LiCus7~i}SU5o4K*K45c1LhSGz0O1o-BV0^L1~i$9GM@ zFO>erD|s1tbiK>4L9m(inbWj~asvAc;32Q=o=vGO z-liYijosh}Z{T}xC~sBj)>k{BBPday{t$_bgs(^C1lGH+Jq9xBSeQFD@DIAGY9G35 zYRL(_;h&xxykZr3xv0(!e1>9fV85CGih8EPl$>DKoZu871kL$~*Q`xZ7rC2WWQPsw zy~a(Mg)>dO<%WE#)h>)n-3RP)1G~I|4XPU^uDS^{x>nZ_(@^?Jz$ta>3our~Xt}nn z)(wBIP!EZRvR2G#rj5fyQ!6zchXF#VdY=L?^l{KI)En%r(x|s#-wJ;(Z!n|O8yM3& zoDJn>K6ry;5Cq^20#9{i^H7h%2Kp*}=@MQ>hOdIl3IL@#3R+D&@key7*q%_SE$UqK z+1TPAK~p-i|G;)2ua5e6B$B!{uz{BT3@E+9JO%I$kvUeoz{EFW8~x7Qq894WaDbmc zT+IbdJ%wUs`oXZzf~t%fk%;;dn?4XRD0e`wG~@-Ko!YYdIv}}8T?B%@+r3pCilUA$ zJ^yn8zj_0Ea{~Wj7O+Q#6rk4sD-sD!@7d7O&7HGt?a!UA!ssHS+}EDXnA!+Uflt{z z{Q+CNf!E!QJ53P&h+1RP-7u-CrEWw{Fblc!W5klX@lA>a4>v&-oA>Uf{W_@Zxlepr z)Le`>^#}I%ca)H5)R$1KGB~!tcEa``>`*D730r?$4PLncX*NWg>A#dZ!U#2E-=DwN zkX-|o*oZj#ijl}T8XS$I$+0+62ctTC1QdV~3htNh+_b3uPPamJeq(t)fs>O*=g zn6+kiJ%aA5dI`G27faCjF%5Lk-3MFLd`O~IEWgC(gI@}OM>G62-S!u9f*MS#H5Ru4 zo19?hez2@*tNRAxof|AolJN!BHGI~|+wfC|+MXC)q`vN8mpi}%``pm{)v6V}BVQBH z$pm=2L0jw(r9XUmTpaF1h`{&m##QtifNhrMd)d79JJF=hqz2fM8}z6fQ6{kN#);^V z;N}Fz_Up}%?aHe740Coz$TX~!y%ZpG(0ZqM=n$K|Af)Sdon{)J9vwK3QSq5mS7l?F*gRMEOj@IgWWkD zHe{u?q;AgK(6tUDWxG;HW!9hTayP9d)`5unU=N2M$wayf!mU|N-_$M;%kP3MI+72k zmjK$abo&ArWPtye^c>I}(8ah$BN;o1jj9~g1idMUl|MW%YJW~}Y`nxL?g4M8L5}yHqxXU?-L?{K#n3Ncp0Oy07QH9tZcuOI3W#4^M2Mm6 z1z3RbYMem({VE_$B@8MAhgNlpup)wI_-pLaq>p;xiW|R#0#yZ?qb|i2eRPmMqyvt; zTKC~@x)JTegJGzQIXngih*vM=h=Nxv4PQo+P6CCQ6hD97=hgrjFDLLWCJ{CWS9-X# zU*>JNyuZso1}kgrggiKFS`@#$rbwpjdHg-F5lB(LKy7Z|@)R!HV*`7v=+yZj3*K$o z>fZrX{v*)8dJ7GpGB;4{@jsOtEbh-m;W^PVumA3qBL9PbwOCO57qqQ?d-r{9=D*pk ziQ(@X!-vuE3(zdX(^+(vBm@1~jWb6yEv zFml-LHL|~wZHE6X(O>%+&HDT9R~$Ue{xO*CMJU#Gp^{2(!zk4mG-dQ-y7)YZQ3m56mI|&V#O)DUu&}-YJXtM*Ud5~Nz8#Hy7Z5y)5pookItO;8GbV5N2&g;Oca+V zslF)W22O%CNisWRp3o*v5qVzY&A zHgZEUKwAbJpxHxhR1bi}4u`6K3_G%Ff^J4NHDA-85qIMyFaoDA zf4t5k=LYk@mxk*kDX6nSV-zJo8T+c-z)zVkF#V@)=FaK{5te(%?{$%PkiDfSCkuIE zMyq-dEYZi+rF0k9f0_~sF=k+-7YlwM#Dfxb8JegrsLc(0OX;7){HA=?ed~0B1{+ir zYKYNZbqdv67FnS-Ln(g@j-HaGbgs%jnyN?l!+yP>=S7n25 zV{{aK8Vu1yKs6kWw4q`PpR^F5-qb~Iq*^)DW7uCPeLz)QnDnEm43mxSMs+lIt*y!h zN#gz;VBu*%GmOTS`oCl`_$&b=ITd}VwbGI7^G<;_^`y{(=|eJH9XPi~?IEUpP@^&3 z3gc`{pZXFy=0iA&skme}pa!Ngc0hIp4bgFT6>Ib@&j-+jA~F3LrU<4dVpNE`f~6YM z?;U5DxO<%d1VeI95K8|NLvM@ep-^h>6BpEVhvOt;V=gXuH9HKvb2 z(#G^0$QVp-WHE+mM@Xvq(ve`g71e5{(1PhCYB!T{oUk#MB~CZ}!@+b3jI%Ml_zUPb z8p83I-iihmrrSUoOwVME#`J0eq%nOMpbMs5F)CnMc#X#N9>*C5(@M}WOmBoQ+hY2P zw2(MG5&8iyG0g^7RkOcP`n~hxFkMW845llN(wI(%q>ZUU%^$gceNqqosrCciJ?AsUI~uPMHsFOuK&$9dCdckLehyip6Q8*aVpk>LWP8U^-AY zW1JSior39dJnI9dPd8~y$1^Gz;0DuU>Go)xj)X7UVp=9G1k*q3A~F4*Lp`4Th0S_1wQZY7c?% zphjc*0gSUTeQqaoTngcMOj`l9g=vb|B$zg_M#t&jpbJG}8i6T-X&s)Y0@Lh9jp<&; z83xmh1R#oO7(;K1=@C$B=Kf{6NKEhHP~T*Kq4cBX#bNp$4KkSaM(@OQH6(3JGazFy zy_v-rrd=VaE|rc1(+^Osii8$Sr&7C_`{xPUnfq^l=3sg?jI%MFy#qRqgK#{icc6iV z=_eq~+)rhV#`GEjq%r*?Ko?Ah;h8ls9n_#Pz29+$!L$Z+4AYz8%eI)Vl@=1Gr$E1% z`{Th?3)o*M{k^g{OzUZo!E_s*pcB)JAZcUzH6q7gn#rNWFnx-OkCToB)2mUfdI&9; zc9h}jIQ>DJX6Ak!bm}-A2)>PJ&+X8$8O(T0v(do9bg9?`nGNdiaDu@!O*dnlPJ=rI z(|veP0GQr-mBw@;qr#f|ed+dSoMyt8Z84oMEd^K~oK; zccFJ;ngmH3(-knK9^`#IDaKYhav>>6}lX;{*uD zV|ou7SeWhrY36=9Yc!_U5g>1#_grVl&LFqkd`9mDiC__8ggZ%7M? z(*e*gb07O(aMfk(FO=RDk9;jm8)=ZibRv2urn4YvW4Z^CV=&F)P-2)qN5v;dM}p}! zs8)vxEtqzd;p#a3NtlnLG6SS45mYL zGse*jxKl8#bPJ|$U7;~8U{qLh|0KFS8mC$CWm`-yl@@~O2f9f8KXa(3u)k1xO9`IZ zZpH~R?{m^==rY#mDE&e_C^P>c6a~?PFe=Radlzd& zJAiK^`WNw(v*Z6BLvM>{UuhwTGX6}IKEk2C2O5Yj#)}M5M0d~}gJ?q!jp)mevk}dO zj6w8X7GsDW21#{=bR&p3u+amgov=BrY ze+JQM;HsVy4ap;?~{u0R9i2j7AF^Ep&Kw^ltQ0?i`jUd{LYIUs8 zf@rb~R>x>(VLOOk1D!fX&w&mb(LNtS$A@6XBRT~QEJSY+n;^46?S=~sq8YjwXQdC$ z1fsQF)LV3GFn#eN4e3Q7?I1lvs+}O609Uq!^fGB7kZ#vScF-9`brw4erSF?%L3%bV z6-d$f1ZmK!j)b6%=|eEuVEQwQF-*&;_d{tWn4SZ5YNODC>B}-)jp=G(JD8@SMq|o& zvoYQDK6ErdI3CjuR292}8cjp=o&K$Gg2D7_@uAH7Ls8V2E+jLUURS3vO#*3Sx=ozr zVEPlr-WJnSq=jG_)J0;tnq&Q#xqCF0#Iv!iqItbdBPJ)oZ^kEibnD&OG zYLI>eQ-x|(BeY;zO7&*uUnFb?(@#HeFkKGYY)t*{LC0ATj>q(IG_WxJ7No&+3~Thv zUqO8I%zp)-YfMiP(9*wNpfP>M@rIfDjp8f^(}&>9wwP{}7J}(e=rU9PB5>8U)E!D+ zWyk3sXpe)bj>lG20YMwn{fHccX#s~4!*o6Mo+bSVrpr;S`U)+W_LAZ1I873^gXwk9 zspB*QI&4fme}#^Z!HmcB0yMBNyC=krsmK=eo!al2BBG*kLF=X{HsYqiCsvsgB21bqoY;Odo~O2GavSs#`F_$mV@bjjJ++U1Ehsux=a^|=`$Sb zcIpnLZ=GRbx|{YmnCf_JRU05^V>%T=2Gc*X7{jy=B-ORjk6`*Ws?|cF1=Dh>H*KxjzeB6{PM^`mzfxOmC$<4yHODTU9j#ZA?3g z{c;C2jl~$Io2Yk?^dp$AK(#taXu-5M)f-F?5w?Tr4Twe^r(>bR#DAIgFx{n# z?BEa-)lhbbCqWljn2w>P4yHODTh;Lpv@!h?j5cxFNk;aHHv)YNMSrWh=g<0uj1NIW z|8~5E9NqkW&hb+JM(itoAi_a;N`=PUw0S#jg+n{RRf#Cybs6;c< z@oESIW3^AN5*m3Z8ZX@^QGsl-L2ZPweEQi%ohbuJKNn`QlUGq;9xJWma}UM~fOsA- z!aaBiNS;;6kXzMG8L~KN9MmA_@midk$0m5isQ~uz<+LDs2&MnY#`0ELC2!Hegh$!H z!4fZKeyaKt>iD;#{tCFfSFPvMLF*M1JgJuc!q?+iLqA_sGoUWK7q{ew9#6U_j*<+0 zHtF|b^y#EWXUz|w3SmdpDghm)F)<1^Ea@e}9S*rOCrP(Zf^G}qfv($s72`pW^2c@wrJq&&F^x1yCZ$BSa@4N-* z`CN3pdI}DN<05!fKl(}*!%_vH>N|IGmmiVR5KZvA`T$X%xuy%96j&?afkd=jZGV%m zi@FpQ{UoD(ywUzNXoJiOt^K$Iv{xGKdy$w7GB0DC?I82UW{u3R0@-#oC8m9Z*8U;B zG7*pap+@_?G3^((uYIo3{)ExK7qqec6M}?O(gU&o5{oB55@E*pF zjL5V)9FV;>464+2Fb$5+Y(jeDi`digD$VOjISq^Z;k}ZkUDEe<^(?H$TZ=cW0nPUx zx8t32l>v~{<SjJbP`A$*>y2bnA**XU3jK|=9 zHI#@UMV&={DE-s(qf-UmQNtPS&imqDV<56JZBT#N06w4#fQ9$P19*vYlRAR~1u}SF zd?(za-xrS>+u8Y+2w#3b-{|#tgLNt1khg#8R=O5Sb|Dz3#M@AZ*D5idnSA}dkAD5V zo$)MWr+Pp737V?8pgEpG@+!PsV*M-tI=l zWk;!x-wT7F zx>Co|-cXPAy87?B`dNl@Dyx545C3e0+E_eCzpsM)(QLkZQ`$CvEQe(#fBZ;41v}xD zaJ=v3Zp_8^uxR^DP)bOT1DzA>)$c$|hvB;!g6Xv|0ug{E#ohP;t$OZt8K=5igN;<; zZoCQa>!6!pRWjZkTlNdYQn%tQN9^199$-#zK}uHY=1b7^PUe-h?+$yOa~~bV#b_1m~=J^*9RARZ6~k@RByk-FP4E z!F0TYvcW6r*?0o&#w*LJ3z#(H?_dy&DQp$&#P79SNO^f}9)AiLBXYdmsTGDlj*#Z8_ZA24SbjzxVery{F~R|>mB(W0$KIuP50%rgpjVso9^D?y!zar zNV*#z1?st>Ly}~}3!|YWb3=!^+(6z^RY7xuc}p|vha=h7Ys4Gsk~_F>=!AU&JI!hM z%I>&N+m4Ub9k=cEG3d$-^|5>9OWv6qI-%#8_3B^HlN+1~Guivu=)Ia92Hu5T^=g6C z<^kiZrQoTq2pHIpc=O7O{6GDQ4L@Ee#%u2lEuBM4Bm4L7-@E06wO8$|$H%`buxYJI z-n+KG-sN(S-INo`=$Pvs+Y;F1+LY64*yX zem35$*C?zj4gVXfy1E0V=*T)0K4xScjpoXa25lniFXUeYK2zajT;l_4wg%2WpFwp5 zs$mLa>ZcZHVoW^={o&_hb|N2CaN-~zy!eZ=pNM{6<&PqW2yK!8=_dgw$%dAo+~Fh9s(&Cy>$e%fan2HjBsMAa=i;eBuxk zf%Jay-QNstHV%J7y0UN>!bZlJV;o}`9|nhTCvg$?kEe_N`0+!zI@~d!yEfqd?D+9( z1Kf?*=$_T<3@>N=uSyx?2Qz#$g2x%|uY@hA!(;=(8;+|&esQWlMKw$mmXSLCK&dqc zO1Ug0w^@D6CO_2U6j_$iM~!2)8(EKUd+WvPVj3Fi(M?x-bTvJ#7q3yMR^6d4wqK6l z|N5Nu>wxc9y+<4M1RE}ai1n*KUUqgjHZnhA4c`g`xqeLnt-m+`r(99hpam6Y=EIyjD zA%bXfH{M`^`3Kkry-W`uzsw@ePv~&H!t7&FRv3|wt}we)g$Tv1Fqd)=@hgnZgL{=n zRO1_k8`ZzrP*!OF?Ktd7QN1u^yg1&_;`TP|*yBBIJ^K#$mg=#eLOX+X*r~TBDb5$( zC7&S7PFmt3TVf&nm=nxPVKUDQwBX2SEY{8w&_!;s!k4YwOS2%Jc@-uFzO%Tj158$j z!y@y>Zz*jt+Xp}O!r-wo(psz*Uy;lbvQtj*Nb~*IFu!Sy^A+*NMnr(w%$&iHdLA^r z@dP6ylztoH&dPBw==_!f=T3B{PBr%Q)%GlnpX#SM_I!q3!t;Pp8@+c*S32K|{#|IH z*Q}W^kpA_-)v5)B% z?+A%~4@POeSm{R-H3ia`*aH#g062RzFC&)%XFc!dyeQRfUEN<-yKt(g=Y6)Wt^y8p zkFNfS)$(=U{-}1o@9}%{!Fm{E^1*2w9QU(2AIviOU>zV~K1fZN50VgrFMJO&GG;mcO6U`x)qjsDvtA#}o+M@BF| zGqH=mb|SQ>D#(o0U)X&Ewayg%h(-rZ9^gJcnklxU0W-y3VH$}v5jVLc53bD%&QHN$ z16hrV_Kyu_HDY^&7i@C_VeZ)$p)WXU>7lwG90Vi$+>PZRIsf_PUKb2C^OWC{-6)Ap z&_4qmsOLe;{AVQS0JG44L661VboG8z%lxN5IRE(@ed6Xn0~PcCt6v>{bbodQMBB{M zU%=AyKW5LJ=uDkz?CGoRSvn>z8cuWU`3}9bH~+biJM%%$f3z_39|p?&hig>}hT+VA zcDow1%zs?l%zuc>{J)Z2a{fE|)l1MAJ`SAdg#QC%FxN*Th5_b`b9otgCnl|)>z6$z z)hFrdb98mDOlPjoK(#uBIEH#$iGf4KDlKymRmg-N3Ym8AU!&`PUEBND_n^^P|2df0 zd_TUkS^oh6=X)CH_SgT_oGLsM*!V1gGV|Tt$XTXWxg#Y6>ylI#K*-4MAx%1&uW}a( zh3W;*;}jL=WzMV^hzjP4oQ7{@|L_p3W%CN?<9_0rXJ|cUqTbw3BRqWG(8QgYyYVN? zADNUDFl?lml!2`4-Pdw+qqbpWW?r62@Hvgw;rssVH1MIGUN@Jbnc5FYec$K}K1L1dT#bb*xl%bg0aJEuXi``84CuJ*R)lp-aV+u2_D9&w|j{-?3f`fv_ZZ9v}jTx?MvQgf5)O^J&#!9+-L7n zr6LrU^=LY>UfqHB*~||QOGlC)4xyd5f~K9zs7S}7l^<>cDl$2y12D%$55U9D#ySIh zXTHdM%#P`Q42{)LqyH?eza<`r;f{XJyWMv?`w9~<8%o1(V!}E4?fu2g-~(>#ONJ0i zv+RqU!-Z9_-MFa-&07JQ!*Ax8aC$m2&P}%?HZlC@dBYP-=DY>e zClzOlGTFL%p3+X+25XFXc!SuUq4#B@(3{Rv&!WUU^$Pr~ddKX!0-dQOV~-2h_&n89 z+v09|2Wlld!ygjay>y=}hr6LNnyo%2p(m1RCDK8eRE~XV^l7L^EnI@3-!Pn)k#o** zven~H!k#)d3-vf(%Uq&m{s@$G!V5qK)lW$lOaE9`pTlZNW|yG4&Hc=OINwa-SoFQj zeBfh_6ywe}yTBwSv;Ta)IUX7$mqgDu^F67X5i_5`TR7kJAQIFyvQq3)#|uE#FZ)S& zzF9&^%*Och%}?PU`+W0mc8<7Q0F+~KDd(G=G+ce~paO``B;sr1YgKD)4YVGymKj66rRvA2x!=T&4^I2&8eR%#%Z_Be_=e)S8H}Kr5Zem5S zMxI{`(W{aAGspkC&Wn37vJb%X2DG>FoIszokLS}s5P-csL;&k?wu9&HKcPve$8uf$ zxUOzOkm{}X+o)EzLamLb`Ta&Xf^Ww2CZ53`aKBvw%M7NQ;Sw9uW0`w#244iN#PlrE z?VZ7|lsu00_F?+m{Fa&rkzUj_kIOh!#S>D2Y=*nTxtl-T&=!@ z2Ax@EzzxhS#b~Nt6}-0dzWO8v&Yy(FcK1OP;#14hx+{0%dDIC7vneYZ(G6;x*t1>j zhjOmhAAojF`Y)uMtV>F^xv_O=i$p}+x^z61$M43?yx=JMMn`coN*u*qbk9EO(T`td za#Tu&xIyi}HGUA^(%E?QBELuHUR2AbVuQNoG0~vT1xtP*2RdzpwcH@I;`UsfjOh$_ zs^ci&wbnEAi(K&m!9mJRy~7x8MzNJY0iIOrs_^%JpYh9n*Pfmkr|0Jq4UGBkg=Yp{@(k+XQ0)@>(K-$ zwm)>vhn~V18Lq$Md}uG-@9YoTJ0IGB-s0{D)1`aaaomo^>SWMda*x9mNc08-){f&; zh8t{&o(~a!pASug4-Y&a>VS5M&xgK;*Ub5l_m7To?ndW)sGp29dQNe&kcrNR9u{4C z|HqKK6}0UC7#X4TMTkqw8@K81tn;CV>7Vw_hyDa@oG1Us^P!_+_AEwcs++MV!hS;O z{OzNbJqJ1V{O<47WpypjcXs+CZ0_JLj4Z8K=XuoTz$ymAY@&x9L0AG#l! za6a@HO^lrnJuc*d=R@fPCe)*+EI;X|;zb8ceEybIJ*mg7lIm6r6yr_O)jO~s(0Soh zU7fG17wPK1Av5S5RuZb6eD-_u!2>YJ?XdEVt*S)3!wqO+v*O+zJIe-3M-{;x)hev@W{cJ=_Gyh?T%zp%*T8Uve^Pk-}OBiGR zLqW4|Jki?AdgGmfX)6d{#Td@+Gd>;F%0<*dJuc8PS8JKi&vK^yp^(wB08h<-Cv5i-qF46KF({NF62m85?z0Spc)RE(UmI0Nk0~Yw4&>5 zh!EPw@6ew6&aYsHnFa6OCk|5Af@RkFuUV8?u(i!Bm@PtavtSa2f>}^%oq{k$sBBom zRFtjfwK=^C&;VAi0kAmrMUOg*HA5^H6*+kN!=?Cw621j4{4#kcS6zWA(#c9Qy^Q)Z>hOEbeKZ zLL>aPxH;-HbQV~*_N(3vKXtBMd~(E%)ofpBZMCYW!FtQ-W7LkUm!Iu%-#J9a1KH*l1d|d0r%c@Dla2HJ>AJmFW)28K3%;; zS5F<_7HSj?3dKyITwvHTM<`6mrpnSU+@-Tr=Khm(I6LPO&Gvl)sE zG6RX!3j*5)^(3ws@*SteMf6LI6~@M4oG?K55@{|6dK2#!O{yDPYKN7xDEa3Su_m?( ze+DmLQQTzx7UI9?{A2%)P)RTwp@jM8T{;`Dfaza^`iM}-Kf_=W47rMy;d&4h!|f21 zDbBMbotO4WUW%Qn=WDf1El?z(^P0||y#4P7W$Fphv_U;gQ}Old{&7e=N!J63rXTG2 zguJ1i7mp!7eS(?;^V4`(dv?}RcT;CccTCt=ibgrPk5Ab)ma1tGwDP?c8qh{)-Q9p0 zn@|q8>s@9K>b~|cxS5Hz1{efu>*WTbM zK%U3Pd6?t}Yb*1bHp_E_IUsX_hsqa4;Kn3UH z{5u$N_-{m)W(J&rQK{!aGdDbeEBt;WX0?^mU(mzB?>A^pmao;UCzt`Z?d}=N9&JKgJh!$&(YOa z>gs7HJL&IkRI4(W2^H%kH>U5_GPzVC=iQen{n)fkeoP_Hm4ZgJL+D={vE&lhmDsuZL*sJR?(D19|T-=q6I z`D`|7+T^pHV719-`O>rzR+x2cFPvlSxQKS_0!=?{X9R@O$Hm(bUSaH*Ks#n=J7izj z_ZGC%=M44gM4$(BhG*6LFP21fW2~1Sph8_`dRe47XmS7JL_(`2HK)q+QsT|jzZ7eo9H96rM+0J zj%{hrfwj8N*52U@BhfY&vyE(D&(JOEX)HIv-R%}r*aCkC1%6VO1NQK{Kf|HCS3DE_ z>*RkwM**My5k68~q1QNk9^};z7z0;^Z*fiCis8KgjWYRvfw+!)e=+8QdJGbBZ-jid zT$HFBu);IZBa(IqCLm%S>ch*(T^=XzzX4fPSLo_%b#-B1C+|OmYIP|rRFC1G-M7T$ z_y6#Hnc6nrmsyOA*XH{&N5Mk#fMYR--wiZhs*a#DSbI6_u;$r8ddU8MOnxsz#H<_l z{z0^;3&7&{OXT}qSPD0(y$p41O?SVe9z$`?e|~;&!22csSU(@#Ol{Hk$?`ku^{E<~ zxjvl$y8ZQOi=-W_PuYM|?`RR#co$#ahvQYU&;o#og!b$#xK~x(#Ifzo4Ln;X-p0mk zCRpC$DNDJ!VOQo2eCQ46S37Dj`n=*d5JI_pI4=*m)y0G)DB7gOUiFJWAx*G3W5oO< zoLAU|`V{3{{eWC*@oZ?F`UuP%e)GxQxF6xI$}s+%Kz466i-q8{-g5klgUoD?dYmH* zPV-==i1<}^8!{)j5D!Un@Y|==j|pC`(FreE1q5;NO)*=5#y;`n#$^a{*Br~##{IT zz(f7&SPm(Wof7^RX8atyU(fe1p5q{p-%lh@$DMO7H&PlRDZqP`5;=H2b~EN$M?^J@ zIreCoiWeQ{OvMrC7S*30FV(;Fmg@KLOM3NL__3%~|3H7bpZN3c==XaL*k3&(u*;#; z(GnEV@AoY0%=q1%k*&Yq0~;_u;Wqh(5V!F`Z!*&Q4Zn)xa1Zwd z`r{U6xx~CVNIF#%m{L{^yMD_7rA-(wqwff;@JHM{=N?9w@FHm(OpA9GycxP6)ykwsJQqW zPKRRv(f6Pf9E2&to2Pef5KXE{`;6z{U$H2&B>p`p{Qfl&irZoSg;=zI4h}o-k&fh0 zqBHGW2AXzWOGS7piJ-IQ$&EmQcFHdl5p3=uaC{Cn4neNtQU1PAc1-VMXrzW3y=Q5? zD~^fNJKWLhf|lJ6S$ZPSZ*VN3o>tJbZx{OwrTZ~;Ec^bs%-FXEvoJiv%sXcuI`2UR zc45ADCFGc|Y1p>^7 z?Rp*m@IIG+hpBH&Pb2lXjh=2=&sxlVYkY?~dbYt1bC9O>e2C!~oX(-1ji8CsYaC`M zeP+C#&4?-SV>9&(f<0ItFam#aqqA zuqS$}>2BN&&`c(KR21v?!=FR%%!d4h7+m}oh&A%;FL<5c4sTtGlFn85eg8Ts>g_?D z(d4{6T57cM{d8*UueEVQpw6L^P+bR^pM^oA5oh_e_3p+&%zpePADq$&jW~BRH+1fb zDB~~f_$U28gZMLJW~I0rFP0v#-axDTivQIN3UoPzQhMKfA;8l4Xca2$ReOs79hZ;H z6AAl7(3$Vp4ZESrtlNJ2IRXWYCa?f;cm;Zo?YH%QV;qN$ z{B;H9l7-*9qD2fCOaop6O#_~%s!;kCOeQOztkv=6ZoHGhhCx(Gb6Iz$7$bTJ3x96_ zbogne3huAw3Rn7hn**N)n*B_~75$tS-_He3KgqhEa8H3;<16}3g|QmXy9f-I*9YK0 z6~Qn~Je07XRv9*;{2we}LAOTpJsL2pHNMO!#Axml8U5YFYp&Ipo(o?1bPbyBUpo7c zy>cCUj=725zabp_t)kh^m}}6~*s_hb6@%uOWxj;c|AnU{mNh_EZqzNa>;iLg8;S6#(eDWlm6AWkf9qI!@9P06eB-8Xw{5_kYkq5yI zI;ZYJuc&U;)sN`vs}6N?>Lye>`;PBJZevBGVD? z|G_9`(Z@-*_x@i7gG#b7->~tcKW5N>p$!ud;~Q7by__Z% zBk;vpC`sw-Tc4ESEAj;jZ?KfHl4$ZErkj%1A67_OERLD^N^9+$;hRd?3J-+LU* z5ykJS9Q@>M#B4UvFYG;rp{b#u87pUzkNsbdxL6s^(KB*q>G`1)j5T@eokr25n!u93 zpB??aNs-B0@_ybBxPbZKDa3}^&+vW1ccEF2KZ`yBR(Tk*T17Clc|B;}3eYsK8Q1ug z`)&pfOl$I?w{Q!Qq27g2z2BfD`47me{FvTn*-wVhm`y_uP@H8HH!h)081^rYz`Sj_ ztwHQl&ESO#FeILjvENo1=5}t3C$od?GO7*gL-O%^;1Jl>9Nej+!QHem4{Gx@9oe9Oy*rljbpn_9p3l{A5@5Oq_QjWRvGrF|y#hA;nYv|^_ zf$s;X`Ob{Mh7OB~yKynNW_qQ{yyWwKXd`( z##jl|&OfWqity1JKjZzH%)3&PB1cO$=#sypxIUZ&4!K%2*BE3~A$u`i_fyKwNL z7Jh3Kjv2pIk70spR&dG+EJ>@>?N>)Rc{m>U4$PJ6=BpTSo$&WkaR=9*!7sT+-d{H7 z9Bp#U;WRh?FSzRS4eZEw!K-F7o6Cs%5HvQS>Roy}l>P$3(wYY!!63;mRU9Pd+EQsQ z%lG_x(WFjhOKdh~N>&+5FrwoRcd+M=#ebcv<;JXLOktN3?^qL5o#@B;6_qwzu?jn@ z`OW@=Fuhl)i=?Bh6)?!3L}SKl#>yyT1Q^(B`sIsKX9|IDaTmfc>h1$Zc#>FI&wiu% z@D-gW01NK#PT@2~KKvA?u+IIRgz>QOKrLrZb8(D=LCE>L)b|g+6i0i){E~949)Gho zj!q8u&@^nrRxvB}8+92XB7AlfN6Z4XkmdxlR)zTl1L>n176ACk(~XyrMR1qSE~BoL zYITTIchJ=z9pq#e531E}deeZ;%_;xRq(!5+lDLFx+UKKwh14^zHuLZ2*?-Tf;p<^- zzF3DppRR!s%uk;pNZZd(@5zKhewqQJt^BkJo$I@rj*w9AApT^wI{AtB z5GFqrL4bc4m2R&Ef?WQ2Uqm_`G_G8=&bxxE7S>CY2RiCD_zU%P#_4JYqbH}~8_{)| z(e;SY6~L{ zybA;10y0JC8*^-_=QFX)X?UYFyce!_`o}zv^8Wxn_g2)$WY8zVtMfh*2%cNW{MtYh zFu#sR3+Mg=Sm3O2WI}`hHw_cjjTjBbgZYvz_+q{s zj~YvVEBGewO{V_spsD{u%7@Y$;`Q%DU@)unCq~PqsbI9|a*a`{u=c9WxQ5T%4`KHG z7Ketpx_h $ooVgf>YHN!tN@@Y6j&(<5E2h}5VHJ^Q>`t+{OY^_GMo?rM|a?!tc z&-uoE0RFaVVN!5R5*|_Y=ikcHziqREJ#HM6EJz^0ut}3=l>EcyksavlaoyQJxHyDH z^7Qh>%OI?}pffpl*7^hd%klj4snqLkybdDfFQ=c=(LYPNT{5CUb!ch{j7jnzjMzj6 zuXBCD?`_NMb|;qGOOpa`dn1Uu%bQfjK`m>Zh>nX#w2x!*)utbh@`*6nHCz^ks2?i z#;+II8nr*n@4x~+M`RuA!OUET*VB$NX!*~K`y2D8r~wQkos)400Ud}wX z+Bc`B&@*zRC&hI_m9M&{tj6!F@b^D$U`|ce{3`#V{-+(lpXMu?2exi`E*iFJH^Em_ zJ=Ry`FNM&+foI|WilPespwrCq^2*{Oe_3UPXHHRBxvylPE32*wR{2UiMV`^MbLRM} z2fFggYHG?V=6Z^%=hnsViL^`a`j z%aBWMQVy`Fq$IzfARiatWpr2!zpu_expG2TiEC0pX5oa1h54Cd$L37P7BYYQn1a-H zI1@9o^4nn-WadsT%*~om=*2&lf+#;Pb9#I1Nm*kiPR*L+g1MfGO2223&+h>OasD=F zdgl2S4RoDQT2xU|?z4h(0-E_MDr@JKN<73h)!`HuDhC8xv^EuCR!~}5TV7Ies^3#u zR0TYLOIsS`b1I4}tE&;ckgqBA)RbN38z_S*Du=I17U{vnMKimJ8c|hQQ|2#Q;Pd!Q zBwBTqB_$RclZex}wz{Th0;bOb-@xKxSB!G8YtK0&J!SK&MvR!3S5%kltC;IA^_+5w z=R|*HrKcQI$>*6Z^Xo+92@^}v>Ch&aTpH&y&&{du`>HF7%Ey)Y%1g#n)-pACIOokL zI+P;MptLh*m-&IG-#6D+9fzwcHspkIoaVnrj<{ok8AaZQQVFuhd|ypX5yq&U@Sp7( z6yM)`J=r}RLNUkbId`NdJvEJ;S)U0-6(dIE6)l?W%S9e5KWD+P5hEr_T0PezbrXCG zb=dW<1rmeO3jL>9&0PyB%SsUHB|fJa)6<9%{I@@K9iTO?waZoGhxdy;lLxe;WJ(27 zdIB|`84Jr050gD3Jtis6wC!@r3(BhfwMFIaXkVg-DVDY|%4v+N(>}pCC;8@JQTUCI z8DE0tTzSS6m6y*hDxTLL>AuGAA!s%`r(#a!Ic)(x_Y|ko|6t#g3an}|3zIUmseACN z4ERaTkc(^2Yx?SH>2PePvwLCplnKV_%19&y<%|W9$aGxuab1tCMis7&xJRvDh+9bT zXJNIk$5zyZoz7#pdT@Ok*VWh^{DNyeHmCitH&4L^As^Q&Y%5oh#%%!~xwYWx!dsoQ zaNCoDYcsC-xUR;v3fCRDHshL%8@JWuvs1&A67}>Uty+S&r*!Twlhu{!z%|y5*0N$RP(o?x{%R99&mE7m1XUelZfc6W3X< z0Uumfw?rcU!qv4d66w<&^m^EjYs;ocWHITtfhVphe~Cms!8QK_=*3|{$|ul^>mFQ7 za9zC}cJTTI#)+%zE9k{F{~O>AKkfNvBr+M-{C@*a`U}^Wac#kM2d>ROKrj5X1J@K> zXYGwdE+UOU@2dhOQkS><&>c#_K`#D*W6DT{Ccv%4Rimx|Bkr4;FoIql*2l zvt=?HIxV0~*1;vbWEy?@AhY;;_`Qv6p%J2eeSpI%$Si0h(=mfW;}0HZWId?&LiQKP zUfNdHOQEcTsgJ+eY8%FTOIw+XC^IptkJzn%Y;J8Nf|rS6SsQ>Wtbj7B>8>2ajsnP!9R&z~}*#qw-myPSirsWYan;4Ef*VGowi^CRO{I9gK_mo zZW|DlAJ?PnY^j#HaSrN-p&oB^nem{0YOJ1fjrEDzFGjsLK|Srg6ZO+k|9kCaZr+r@ z9{TocQ(qjl7xOVX{>wQ0@r)P7U+>N?*C9BIIW8)Tu`&2SQ`az4U%>kDW^NnI{SeD} zeZ$-Dpo+RmAe-?Ux*ARW@6ojyvVQ1l4^wXTwxGTd^%B&pX(e<=Vc^ zSaULPLerifIo5ur{`cU<^{o-Q@MOvKpBv42#DeRdANAd%_1SUtTn|frqn_(zV?`u_ z2USM@dC~TanJuUvjP{q(aZb+7ck)6*w@&^0=m~*p%Da%98}E!np2ggV%180)baqD# zSjSnwjrONNzSljG$mwkBrQav@=$fzNg8K4N-w*X=cK(RY-CX2^2sP$7d8r=qB`YJ5 zC#X;CMVw_bFU_Z1mLsvTaJ9>XAi z5%xX57mrfNpYv)Y(wY#Dr0DpF-wMe8vKITjgm@hP|Fw6mv2h*Od1NZG+gOVHlKZ1c zHg2psO|#g$OD;*HHTYUSEIzKq6(j41hs))qv=zx^c9$!%g&p;!q-ayva4IKAni6O$ z$B5G^Xut+WkrHjqIB|c-NK3e>QY(?GxUmbc0V>%2k?nV8&e^?p_g>Xx(tjSu1>f&rUH4pQKayNM7m$;);J@>qYPGi_+ZhY=%SG_N`ZCVaBI|uIFiuy%zxUs2 zwV}{{r*VD1;im~n^*;#3^uh1dYJcpn&zMht+;6I5<|Xm>fdA9~UaLLg&)?5KSI^$q zf+g_3TBy|yBdygR5AEMKjEP3i?}T@H;GG^YJup3BJEEuG(rKnK#{a*&iOeU39$et1 zAkPy`&zhePST^;W{Cq1vfAUvs1aHPos61~et^u2{b~$D!uB4m5$rWx9oA5RMoz@-{ zL{H$~bSTpEHdl<)A%$CbLrZ3z!ZhhI1hd`({W=!_b!UQnyLEOt+X`V|tzGzF)P;4>3K=G|hC7=@ipBrd6irn4V{Pf$2KaO{QB+ zuQ9#Obl(G9KGVZY(@Y1MPBEQhT4j2U>3OCXn65M3WV*%l8q@1c_wh;NA*P3!rkM^h zonku2w951x)ALL(FkNT5$#je9HKx~@?(5<9Gd;{S&2*6I6w^7TRi@{do@aW2={nO* zrdv#}F}==oU#~LZ5Yxj<(@Y1MPBEQhT4j2U>3OCXn65M3WV*%l8q@1c_w{l4Ob;_n zGaY0)#dMBomFYRA=b2t$y3TZy=@!##Os_ND$M)zD)5A<{t)O?W#v~d_yPMGC-)sW- zaUlX9>hHflcHglXyZ~8_b;eWi#7B~y%jVH}%;}0J+COCB@N5HU8?4(4djgPoXj3=U z?Ti1{Hq}m|Hw*S$O*m#>dsBSSE_~37C>NX|o0RJy- z>UJgeKZxIfq=;dh71ZyT)lMu=RuDOt@ls`NiM zVc(_xtJXkljKu6F^z+hyeZI^LM?v?f1FDDn?F8drVtkG9Uu66h#uelDGEV=P0_C&u zq6O|_ycal?dvMSK=G++3-(~(Q-?BJ9#c0As=3g7K&oXTP%J|Z-#mzY}qW7Y`l)uQ2 zIiCW4Kkz;3ZgrOXt;Z%)g9bmKVqDJ@<4-U?&G;DOuLGz2WgTqxkNEADw(x$w132+N z-X!ODF@C8DzmM_e_4Nb5_xQ#g%{O7p;H~mm;e2HM&g|-};cu1msQUkj;XkN8{V$S3 zgNDh~m%)$AU@h}*!{pN{=UWE9yG5SA&v>)`rgNJ;A@l1^;O1Ieqk1N`cW*e}9)Vwo zz}F-29{|4{<9p>9Td+BALDa!UfbgX=7B}Z!h&~EDte&3`eslPY`vx|ddNzXpn-Tc; zIiIy>Z3gB%2hlh-B2*uhwYcm4KmMc@_S)Niq8Y1>j-*Fcg7LMBw=d{P75U4S0;};3t0*!N33AJRiSqxy|`1qI54Htp1+?PV(8q z@`-6~!Ve<&Z-Pn+%jYog+c~YDbVcw#3Owd#x^$PzOlkMPxu%nZ&@> zm#)URhL(JX`J307Ka9x#ZXCdewJQgl%DwnUHed6;8PP9B@NY1G>_N+K?lK|zW(0o< z2l!#-RwMAoBk-4iQ$2hB)Rt@BLnBI`jUs&e4=rxq$0Ir`_`1c-`&>l73_Pqpmzlp= zpS%&lUt|8YCOw?Oii_#{ME-9? z;Ct|5iOO{+Z7w2*9|9iMuH%N^U!skl1|GJ)dM+ZLO_LAyFJH0g&HH*p5B_|3xkJEj z$6KQ2bG)$#{=bO8l|C_^!UgXXF4&JIQ-jNkd2(Xu=gY`+D;i!fnWIO>lhv+dqWO2a zl{_*Imx_+5-2Aea$z+h>iSc&2sO%&fH>;hb|1L9U=cN6h$!ap8k%!Z*wR<#^%|5IL zkB#?dM<&L#4$rv5+-%NNcakQB+uA!zG0=Vk{!z!7DHO9sdp#aKMg1AoRp`ZfSGj4V z)8&e3871njU$W2qT4aMpofO=9dP^sd_Z3c#FE7x*beQY)7zmxVeQpP0)M=lApUv{Z zZYtMplbZUKyp!ZVRnk7s41Hp>QycFBFMMd)Nq91W>N&ppMK&-*eA3nhV5F0;_-8V1 zRtIwKcpEtnjZXCSj%r3fthAmj>XY-u zncTddtrSaTom*Z}dAKRfd+_m!cc#13;Y@n2uvpN!QYp8p;geNbRdc1>f~RMf7Zz5L z#P_7ZSqZReJ$STtETc2y12hBl(D*T(8D?;J;Hc8vsENVB$xK#fd;3N+#F!oHuP2%< z7q#_!QF`Fv@!qkKel^kepsuV`l8f+@f(n2PIqg<-vL4z5f2^c4=~Y_YWHJTjXGwE9 z2RyXUn>e%Rmf)*Zs;p)phYgAB>@UJ|W~Bm=Bt=0&+CGjB@IBXO1b%ZmC7a#~+}~!F zD_%zRjZEl8?~GpX7BqZ)s0K#Gr0twbTc@CCS)&9ZJ5G9{$)k+a(c7J~ftTYiE z%P}r@JIafiRi;KESH~F`*6(0bA_Az1$R_oeInVBnR0dih&!A)s{6CYb)l*ki^gTe zbvnK3lFk>FPC--TD=VZrsEPSXX`ZSv4){jcYZgBg#2skcZ@ zzeAk*s+~vIiblZl(}>=o{V=; zbtGda?HOND_SJ;fV8)%)ih3HVo_lm=brG{h8FhlhPB)FQ5g6z$y_ADeDZ6R-(X|K; z$qtP}b*|)*u5RrdYY{_#+L7g^dL;*>UL?rr*^mmE9wL7>6A>R)5`68gs0FM&iusn# z@`--;M@i60{4;L8;1))6( zUnx{t`XEG2I}R2NBk&l@E#|%8^zdn3>Y#L8VCHhvhzMyRDGftKLV=?BL#DXj@Y`)O%*enk7V_47Q6VW2@@fP|^$`KVYjc{Nm;w$>Y(X z%3I#->XK(xIK~`9`6l$z$428^mPRe@2v*Y~^CDCcm^pk>~92qjk!*!BAAY{d1rO;Yo znvogw8Ocn`7SG5T>AeCJ-y(~Z$hkng7HMqE<3lj`+zJg+aCC@t@GFT+f zSlRhUt4W{(^I67=zf7`=#zU^U`)Nr+r&Sr3)+=4m^5*jqJSSnw8WYIuXfnIm4{AMA zF59gIW!RYWP8tfWsfz=)udV_(T|n;+B<(8B-}SBXhDAs7DxtoGq&nqK>-?$HO&ghZ zDzC*9$e|p5Y^Ng)YDwcjK>7>|0NLTp7EXHQitKPga+HOr%m;_IZ~PsbT?{E#!RZS0 zsrd|u=_;S*v{svUF(HD6rnN3pLV9id4x?lXcS|4A}J&v(~P!#Xl%MIM-M!CjCvz?cBj z>-H!@&MB~@Fy}~SUir?EqNWz_cu)%&TBC`1!)PZ?i#hPwpOEQC=e?C;1skux{PS;A zsCF>}0{6Q9Rn*<}`7)P8#|7ZA9{R?q1A@U0#RrvDVg9wh_} zTSLBK*>I?vUs`Q!;v8cse_C65(r08l#|E@HM)NBfS}OcR>pg!nN#T@5KL!uU0?jpV zE_m`nGjxsRPJ1_4F1b~g?P16}z$y#`S+~I3L9;QZ0%!qgO(i4{<~v1wq2lG$g-UJ) zv{JJ4l*I7;H7|~rVDXvd!u;$<@V>)5(TB}ce0FsaDJ`v(>@N@z`qp0HLF2cQH=m;f z99x>Ns5q@|R2AGew{+a zkJB*Y4`26^M>UKX`BX}J@xKu|&IzRc!YA|?(vy#-Jd2->&}lA->Q6jUe}>g8BJvwy z;?E;g{6eLCNiXeRhm z^wW}%X>)!r11H&)^y1eQ`>stOdPw?B(u*9Bc=*c~|F47OIEAonN&T;+7y3Q?;!j`q z6T4!Q9G8l54w6nN-G}w37k`@Rt2V(jrxOyB2ve#bzT#cDuHaNYs(}4IR<;wGa zBSPgT1Yj!Z<({qlOuQ8Qv`IwG@7rAdYq*C key encoding, default 'base64' + * @returns {PublicKey} + */ +function openSshPublicKey(key, encoding) { + if (!Buffer.isBuffer(key)) { + key = key.substr(0, 3) === 'ssh' ? key.split(' ')[1] : key; + key = new Buffer(key, encoding || 'base64'); + } + + function parsePublicKey(key) { + var parts = [], + partsLength = 3; + + while(key.length) { + var dLen = key.readInt32BE(0); + var data = key.slice(4, dLen+4); + key = key.slice(4+dLen); + parts.push(data); + if (!(--partsLength)) break; + } + + return { + modulus : parts[2], + exponent: parts[1], + type : parts[0] + }; + } + + var pubKey = parsePublicKey(key); + var rsa = new RsaWrap(); + + if (pubKey.type != 'ssh-rsa') { + throw new TypeError('Only "ssh-rsa" format supported'); + } + + rsa.openPublicSshKey(pubKey.modulus, pubKey.exponent); + + return PublicKey(rsa); +} + +/** + * Public Key object. This is the externally-visible object that one gets + * when constructing an instance from a public key. The constructor takes + * a native RsaWrap object. + */ +function PublicKey(rsa) { + var self; + + function getExponent(encoding) { + return encodeBuffer(rsa.getExponent(), encoding); + } + + function getModulus(encoding) { + return encodeBuffer(rsa.getModulus(), encoding); + } + + function toPublicPem(encoding) { + return encodeBuffer(rsa.getPublicKeyPem(), encoding); + } + + function toPublicSsh(encoding) { + return encodeBuffer(createSshPublicKey(rsa), encoding); + } + + function toPublicSshFingerprint(encoding) { + return sshFingerprint(createSshPublicKey(rsa), undefined, encoding); + } + + function encrypt(buf, bufEncoding, outEncoding, padding) { + buf = decodeString(buf, bufEncoding); + padding = (padding === undefined) ? + ursaNative.RSA_PKCS1_OAEP_PADDING : padding; + return encodeBuffer(rsa.publicEncrypt(buf, padding), outEncoding); + } + + function publicDecrypt(buf, bufEncoding, outEncoding, padding) { + buf = decodeString(buf, bufEncoding); + padding = (padding === undefined) ? + ursaNative.RSA_PKCS1_PADDING : padding; + return encodeBuffer(rsa.publicDecrypt(buf, padding), outEncoding); + } + + function verify(algorithm, hash, sig, encoding) { + algorithm = textToNid(algorithm); + hash = decodeString(hash, encoding); + sig = decodeString(sig, encoding); + return rsa.verify(algorithm, hash, sig); + } + + function hashAndVerify(algorithm, buf, sig, encoding, + use_pss_padding, salt_len) { + if (use_pss_padding) { + sig = publicDecrypt(sig, encoding, undefined, + ursaNative.RSA_NO_PADDING); + + var hash = crypto.createHash(algorithm); + hash.update(decodeString(buf, encoding)); + buf = new Buffer(hash.digest(BINARY), BINARY); + + return rsa.verifyPSSPadding(textToNid(algorithm), buf, sig, + (salt_len === undefined) ? ursaNative.RSA_PKCS1_SALT_LEN_HLEN : salt_len); + } else { + var verifier = createVerifier(algorithm); + verifier.update(buf, encoding); + return verifier.verify(self, sig, encoding); + } + } + + function unseal(unsealer) { + return (unsealer === theUnsealer) ? self : undefined; + } + + self = { + encrypt: encrypt, + getExponent: getExponent, + getModulus: getModulus, + hashAndVerify: hashAndVerify, + publicDecrypt: publicDecrypt, + toPublicPem: toPublicPem, + toPublicSsh: toPublicSsh, + toPublicSshFingerprint: toPublicSshFingerprint, + verify: verify, + unseal: unseal + }; + + return self; +} + +/** + * Private Key object. This is the externally-visible object that one + * gets when constructing an instance from a private key (aka a + * keypair). The constructor takes a native RsaWrap object. + */ +function PrivateKey(rsa) { + var self; + + function getPrivateExponent(encoding) { + return encodeBuffer(rsa.getPrivateExponent(), encoding); + } + + function toPrivatePem(encoding) { + return encodeBuffer(rsa.getPrivateKeyPem(), encoding); + } + + function toEncryptedPrivatePem(passPhrase, cipher, encoding) { + if(!passPhrase) return toPrivatePem(encoding); + return encodeBuffer(rsa.getPrivateKeyPem(passPhrase, cipher)); + } + + function decrypt(buf, bufEncoding, outEncoding, padding) { + buf = decodeString(buf, bufEncoding); + padding = (padding === undefined) ? ursaNative.RSA_PKCS1_OAEP_PADDING : padding; + return encodeBuffer(rsa.privateDecrypt(buf, padding), outEncoding); + } + + function privateEncrypt(buf, bufEncoding, outEncoding, padding) { + buf = decodeString(buf, bufEncoding); + padding = (padding === undefined) ? ursaNative.RSA_PKCS1_PADDING : padding; + return encodeBuffer(rsa.privateEncrypt(buf, padding), outEncoding); + } + + function sign(algorithm, hash, hashEncoding, outEncoding) { + algorithm = textToNid(algorithm); + hash = decodeString(hash, hashEncoding); + return encodeBuffer(rsa.sign(algorithm, hash), outEncoding); + } + + function hashAndSign(algorithm, buf, bufEncoding, outEncoding, + use_pss_padding, salt_len) { + if (use_pss_padding) { + var hash = crypto.createHash(algorithm); + hash.update(decodeString(buf, bufEncoding)); + buf = new Buffer(hash.digest(BINARY), BINARY); + + buf = rsa.addPSSPadding(textToNid(algorithm), buf, + (salt_len === undefined) ? ursaNative.RSA_PKCS1_SALT_LEN_HLEN : salt_len); + + return privateEncrypt(buf, undefined, outEncoding, + ursaNative.RSA_NO_PADDING); + } else { + var signer = createSigner(algorithm); + signer.update(buf, bufEncoding); + return signer.sign(self, outEncoding); + } + } + + self = PublicKey(rsa); + self.decrypt = decrypt; + self.getPrivateExponent = getPrivateExponent; + self.hashAndSign = hashAndSign; + self.privateEncrypt = privateEncrypt; + self.sign = sign; + self.toPrivatePem = toPrivatePem; + self.toEncryptedPrivatePem = toEncryptedPrivatePem; + return self; +} + + +/* + * Exported bindings + */ + +/** + * Create a new public key object, from the given PEM-encoded file. + */ +function createPublicKey(pem, encoding) { + var rsa = new RsaWrap(); + pem = decodeString(pem, encoding); + + try { + rsa.setPublicKeyPem(pem); + } catch (ex) { + if (!isPublicKeyPem(pem)) { + throw new Error("Not a public key."); + } + throw ex; + } + + return PublicKey(rsa); +} + +/** + * Create a new private key object, from the given PEM-encoded file, + * optionally decrypting the file with a password. + */ +function createPrivateKey(pem, password, encoding) { + var rsa = new RsaWrap(); + pem = decodeString(pem, encoding); + password = decodeString(password, encoding); + + try { + // Note: The native code is sensitive to the actual number of + // arguments. It's *not* okay to pass undefined as a password. + if (password) { + rsa.setPrivateKeyPem(pem, password); + } else { + rsa.setPrivateKeyPem(pem); + } + } catch (ex) { + if (!isPrivateKeyPem(pem)) { + throw new Error("Not a private key."); + } + throw ex; + } + + return PrivateKey(rsa); +} + +/** + * Create public key from components + */ +function createPublicKeyFromComponents(modulus, exponent) { + var rsa = new RsaWrap(); + rsa.createPublicKeyFromComponents(modulus, exponent); + return PublicKey(rsa); +} + +/** + * Create private key from components + */ +function createPrivateKeyFromComponents(modulus, exponent, p, q, dp, dq, inverseQ, d) { + var rsa = new RsaWrap(); + rsa.createPrivateKeyFromComponents(modulus, exponent, p, q, dp, dq, inverseQ, d); + + return PrivateKey(rsa); +} + +/** + * Generate a new private key object (aka a keypair). + */ +function generatePrivateKey(modulusBits, exponent) { + if (modulusBits === undefined) { + modulusBits = 2048; + } + + if (exponent === undefined) { + exponent = 65537; + } + + var rsa = new RsaWrap(); + rsa.generatePrivateKey(modulusBits, exponent); + + return PrivateKey(rsa); +} + +/** + * Create a key object from a PEM format file, either a private or + * public key depending on what kind of file is passed in. If given + * a private key file, it must not be encrypted. + */ +function createKey(pem, encoding) { + pem = decodeString(pem, encoding); + + if (isPublicKeyPem(pem)) { + return createPublicKey(pem); + } else if (isPrivateKeyPem(pem)) { + return createPrivateKey(pem); + } else { + throw new Error("Not a key."); + } +} + +/** + * Return the SSH-style public key fingerprint of the given SSH-format + * public key. + */ +function sshFingerprint(sshKey, sshEncoding, outEncoding) { + var hash = crypto.createHash(MD5); + + hash.update(decodeString(sshKey, sshEncoding)); + var result = new Buffer(hash.digest(BINARY), BINARY); + return encodeBuffer(result, outEncoding); +} + +/** + * Return whether the given object is a key object (either public or + * private), as constructed by this module. + */ +function isKey(obj) { + var obj2; + + try { + var unseal = obj.unseal; + if (typeof unseal !== "function") { + return false; + } + obj2 = unseal(theUnsealer); + } catch (ex) { + // Ignore; can't assume that other objects obey any particular + // unsealing protocol. + // TODO: Log? + return false; + } + + return obj2 !== undefined; +} + +/** + * Return whether the given object is a private key object, as + * constructed by this module. + */ +function isPrivateKey(obj) { + return isKey(obj) && (obj.decrypt !== undefined); +} + +/** + * Return whether the given object is a public key object (per se), as + * constructed by this module. + */ +function isPublicKey(obj) { + return isKey(obj) && !isPrivateKey(obj); +} + +/** + * Assert wrapper for isKey(). + */ +function assertKey(obj) { + assert(isKey(obj)); +} + +/** + * Assert wrapper for isPrivateKey(). + */ +function assertPrivateKey(obj) { + assert(isPrivateKey(obj)); +} + +/** + * Assert wrapper for isPublicKey(). + */ +function assertPublicKey(obj) { + assert(isPublicKey(obj)); +} + +/** + * Coerce the given key value into an private key object, returning + * it. If given a private key object, this just returns it as-is. If + * given a string or Buffer, it tries to parse it as PEM. Anything + * else is an error. + */ +function coercePrivateKey(orig) { + if (isPrivateKey(orig)) { + return orig; + } else if (isStringOrBuffer(orig)) { + return createPrivateKey(orig); + } + + throw new Error("Not a private key: " + orig); +} + +/** + * Coerce the given key value into a public key object, returning + * it. If given a private key object, this just returns it as-is. If + * given a string or Buffer, it tries to parse it as PEM. Anything + * else is an error. + */ +function coercePublicKey(orig) { + if (isPublicKey(orig)) { + return orig; + } else if (isStringOrBuffer(orig)) { + return createPublicKey(orig); + } + + throw new Error("Not a public key: " + orig); +} + +/** + * Coerce the given key value into a key object (either public or + * private), returning it. If given a private key object, this just + * returns it as-is. If given a string or Buffer, it tries to parse it + * as PEM. Anything else is an error. + */ +function coerceKey(orig) { + if (isKey(orig)) { + return orig; + } else if (isStringOrBuffer(orig)) { + return createKey(orig); + } + + throw new Error("Not a key: " + orig); +} + +/** + * Check whether the two objects are both keys of some sort and + * have the same public part. + */ +function matchingPublicKeys(key1, key2) { + if (!(isKey(key1) && isKey(key2))) { + return false; + } + + // This isn't the most efficient implementation, but it will suffice: + // We convert both to ssh form, which has very little leeway for + // variation, and compare bytes. + + var ssh1 = key1.toPublicSsh(UTF8); + var ssh2 = key2.toPublicSsh(UTF8); + + return ssh1 === ssh2; +} + +/** + * Check whether the two objects are both keys of some sort, are + * both public or both private, and have the same contents. + */ +function equalKeys(key1, key2) { + // See above for rationale. In this case, there's no ssh form for + // private keys, so we just use PEM for that. + + if (isPrivateKey(key1) && isPrivateKey(key2)) { + var pem1 = key1.toPrivatePem(UTF8); + var pem2 = key2.toPrivatePem(UTF8); + return pem1 === pem2; + } + + if (isPublicKey(key1) && isPublicKey(key2)) { + return matchingPublicKeys(key1, key2); + } + + return false; +} + +/** + * Create a signer object. + */ +function createSigner(algorithm) { + var hash = crypto.createHash(algorithm); + var self = {}; + + function update(buf, bufEncoding) { + buf = decodeString(buf, bufEncoding); + hash.update(buf); + return self; + } + + function sign(privateKey, outEncoding) { + var hashBuf = new Buffer(hash.digest(BINARY), BINARY); + return privateKey.sign(algorithm, hashBuf, undefined, outEncoding); + } + + self.sign = sign; + self.update = update; + return self; +} + +/** + * Create a verifier object. + */ +function createVerifier(algorithm) { + var hash = crypto.createHash(algorithm); + var self = {}; + + function update(buf, bufEncoding) { + buf = decodeString(buf, bufEncoding); + hash.update(buf); + return self; + } + + function verify(publicKey, sig, sigEncoding) { + var hashBuf = new Buffer(hash.digest(BINARY), BINARY); + sig = decodeString(sig, sigEncoding); + return publicKey.verify(algorithm, hashBuf, sig); + } + + self.update = update; + self.verify = verify; + return self; +} + + +/* + * Initialization + */ + +module.exports = { + assertKey: assertKey, + assertPrivateKey: assertPrivateKey, + assertPublicKey: assertPublicKey, + coerceKey: coerceKey, + coercePrivateKey: coercePrivateKey, + coercePublicKey: coercePublicKey, + createKey: createKey, + createPrivateKey: createPrivateKey, + createPrivateKeyFromComponents: createPrivateKeyFromComponents, + openSshPublicKey: openSshPublicKey, + createPublicKey: createPublicKey, + createPublicKeyFromComponents: createPublicKeyFromComponents, + createSigner: createSigner, + createVerifier: createVerifier, + equalKeys: equalKeys, + generatePrivateKey: generatePrivateKey, + isKey: isKey, + isPrivateKey: isPrivateKey, + isPublicKey: isPublicKey, + matchingPublicKeys: matchingPublicKeys, + sshFingerprint: sshFingerprint, + RSA_NO_PADDING: ursaNative.RSA_NO_PADDING, + RSA_PKCS1_PADDING: ursaNative.RSA_PKCS1_PADDING, + RSA_PKCS1_OAEP_PADDING: ursaNative.RSA_PKCS1_OAEP_PADDING, + RSA_PKCS1_SALT_LEN_HLEN: ursaNative.RSA_PKCS1_SALT_LEN_HLEN, + RSA_PKCS1_SALT_LEN_MAX: ursaNative.RSA_PKCS1_SALT_LEN_MAX, + RSA_PKCS1_SALT_LEN_RECOVER: ursaNative.RSA_PKCS1_SALT_LEN_RECOVER +}; diff --git a/express-server/node_modules/ursa-optional/package.json b/express-server/node_modules/ursa-optional/package.json new file mode 100644 index 00000000..5dc12754 --- /dev/null +++ b/express-server/node_modules/ursa-optional/package.json @@ -0,0 +1,110 @@ +{ + "_args": [ + [ + "ursa-optional@^0.9.10", + "/nodeapps/https-test/greenlock-express.js/node_modules/rsa-compat" + ] + ], + "_from": "ursa-optional@>=0.9.10 <0.10.0", + "_hasShrinkwrap": false, + "_id": "ursa-optional@0.9.10", + "_inCache": true, + "_installable": true, + "_location": "/ursa-optional", + "_nodeVersion": "10.13.0", + "_npmOperationalInternal": { + "host": "s3://npm-registry-packages", + "tmp": "tmp/ursa-optional_0.9.10_1541526082762_0.09868043920674285" + }, + "_npmUser": { + "email": "mkg20001@gmail.com", + "name": "mkg20001" + }, + "_npmVersion": "6.4.1", + "_phantomChildren": {}, + "_requested": { + "name": "ursa-optional", + "raw": "ursa-optional@^0.9.10", + "rawSpec": "^0.9.10", + "scope": null, + "spec": ">=0.9.10 <0.10.0", + "type": "range" + }, + "_requiredBy": [ + "/rsa-compat" + ], + "_resolved": "https://registry.npmjs.org/ursa-optional/-/ursa-optional-0.9.10.tgz", + "_shasum": "f2eabfe0b6001dbf07a78740cd0a6e5ba6eb2554", + "_shrinkwrap": null, + "_spec": "ursa-optional@^0.9.10", + "_where": "/nodeapps/https-test/greenlock-express.js/node_modules/rsa-compat", + "author": { + "email": "danfuzz@milk.com", + "name": "Dan Bornstein", + "url": "http://www.milk.com/" + }, + "bugs": { + "url": "https://github.com/mkg20001/ursa/issues" + }, + "dependencies": { + "bindings": "^1.3.0", + "nan": "^2.11.1" + }, + "description": "RSA public/private key OpenSSL bindings for node and io.js", + "devDependencies": { + "mocha": "^5.2.0" + }, + "directories": { + "lib": "lib", + "test": "test" + }, + "dist": { + "fileCount": 21, + "integrity": "sha512-RvEbhnxlggX4MXon7KQulTFiJQtLJZpSb9ZSa7ZTkOW0AzqiVTaLjI4vxaSzJBDH9dwZ3ltZadFiBaZslp6haA==", + "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb4dJDCRA9TVsSAnZWagAAjP4P/27Bci055Hpb+wCQWR4s\nHVYq0NnLrTcDuMGzpJxI48QvueBMFGH2zUWZWfHuzoiGAoDaTPMtMg7BLV+S\nU2GTKkjgfZYOYS/fCGt/zv2/7pxXDy0cFUFhZWY9e6Rrupwmcdc24uiJHcxA\nazLQpqb9nm/cwXWqs+9gwkidJ6G+VgouujaNkhsvugIZDYDfXmEW4cTw+aUH\nmtjOh8l/Csc+GOxJulW6rOM9qEDOopULVCVowtJb1Rfz/aZgdDE3iSIzcrzS\nTstfVsA30JJmxy87YZYyGyJpRbV5Sig9o3fA9HaEkuZTxzLZxlUW6Qkh4DD4\n8zq1CnEeJAL/Y70aowApumLDojOOhSB+GHjmR/cshyALHGEe6aRmQWG7HYdz\nIeMJT559AtuW8wmf7lOuPGJnrGWpQwqp/6QJIDmptgGLqISOHh8Pi0NBhevJ\nz9KUISSIPJ7GmdLBohkRfXeUDAh8swsuLhG2XmDESbzh7ZntlN1+vB4EmVee\njMI3d7JRdQNUnnEW6epu/bGE73lWUsLJVbl8N1mkMwLMG1V/eAe81ft5Bafh\nTAYdUnA2ZfuGM2OGnuKwtOsMLQLbU+PP10/MjmchCKDXzouuSbVDvmmRqeza\n/KmGnFT1d7bEhzGdCQkeHTpPo5+1tKF/A36RBP4cJT2+d7GjHIe3lhFJUG/+\nOai6\r\n=H75D\r\n-----END PGP SIGNATURE-----\r\n", + "shasum": "f2eabfe0b6001dbf07a78740cd0a6e5ba6eb2554", + "tarball": "https://registry.npmjs.org/ursa-optional/-/ursa-optional-0.9.10.tgz", + "unpackedSize": 158923 + }, + "engines": { + "node": ">=0.10.0" + }, + "gitHead": "0999dcf62cced5102913f925cb4fcfabdd480dfb", + "homepage": "https://github.com/mkg20001/ursa#readme", + "keywords": [ + "crypto", + "digest", + "hash", + "key", + "openssl", + "private", + "public", + "rsa", + "sign", + "signature", + "verification", + "verify" + ], + "license": "Apache-2.0", + "main": "lib/ursa.js", + "maintainers": [ + { + "name": "mkg20001", + "email": "mkg20001@gmail.com" + } + ], + "name": "ursa-optional", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/mkg20001/ursa.git" + }, + "scripts": { + "install": "node rebuild.js", + "rebuild": "node-gyp rebuild", + "test": "mocha --recursive --reporter spec", + "test-watch": "npm test -- -w --reporter min" + }, + "version": "0.9.10" +} diff --git a/express-server/node_modules/ursa-optional/rebuild.js b/express-server/node_modules/ursa-optional/rebuild.js new file mode 100644 index 00000000..dd87825b --- /dev/null +++ b/express-server/node_modules/ursa-optional/rebuild.js @@ -0,0 +1,17 @@ +var cp = require('child_process'); +var verbose = Boolean(process.env.URSA_VERBOSE); +if (verbose) { + var p = cp.spawn(process.execPath, [process.env.npm_execpath, 'run', 'rebuild'], {cwd: process.cwd(), stdio: 'inherit'}); +} else { + var p = cp.spawnSync(process.execPath, [process.env.npm_execpath, 'run', 'rebuild'], {cwd: process.cwd()}); + if (p.status || p.signal || p.error) { + console.log('ursaNative bindings compilation fail. This is not an issue. Modules that depend on it will use fallbacks.'); + var fs = require('fs'); + if (p.error) { + fs.writeFileSync('./stderr.log', p.error.stack); + } else { + fs.writeFileSync('./stdout.log', p.stdout); + fs.writeFileSync('./stderr.log', p.stderr); + } + } +} diff --git a/express-server/node_modules/ursa-optional/src/ursaNative.cc b/express-server/node_modules/ursa-optional/src/ursaNative.cc new file mode 100644 index 00000000..acd2670d --- /dev/null +++ b/express-server/node_modules/ursa-optional/src/ursaNative.cc @@ -0,0 +1,1865 @@ +// Copyright 2012 The Obvious Corporation. + +#include "ursaNative.h" +#include +#include +#include +#include + +#include +#include +#include + +using namespace v8; + +#ifdef _WIN32 +#include +#define VAR_ARRAY(type, name, size) type *name = (type *)_alloca(size) +#else +#define VAR_ARRAY(type, name, size) type name[size] +#endif + +#if OPENSSL_VERSION_NUMBER < 0x10100000L + +#include +#include + +int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) +{ + /* If the fields n and e in r are NULL, the corresponding input + * parameters MUST be non-NULL for n and e. d may be + * left NULL (in case only the public key is used). + */ + if ((r->n == NULL && n == NULL) || (r->e == NULL && e == NULL)) + return 0; + + if (n != NULL) + { + BN_free(r->n); + r->n = n; + } + if (e != NULL) + { + BN_free(r->e); + r->e = e; + } + if (d != NULL) + { + BN_free(r->d); + r->d = d; + } + + return 1; +} + +int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q) +{ + /* If the fields p and q in r are NULL, the corresponding input + * parameters MUST be non-NULL. + */ + if ((r->p == NULL && p == NULL) || (r->q == NULL && q == NULL)) + return 0; + + if (p != NULL) + { + BN_free(r->p); + r->p = p; + } + if (q != NULL) + { + BN_free(r->q); + r->q = q; + } + + return 1; +} + +int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp) +{ + /* If the fields dmp1, dmq1 and iqmp in r are NULL, the corresponding input + * parameters MUST be non-NULL. + */ + if ((r->dmp1 == NULL && dmp1 == NULL) || (r->dmq1 == NULL && dmq1 == NULL) || (r->iqmp == NULL && iqmp == NULL)) + return 0; + + if (dmp1 != NULL) + { + BN_free(r->dmp1); + r->dmp1 = dmp1; + } + if (dmq1 != NULL) + { + BN_free(r->dmq1); + r->dmq1 = dmq1; + } + if (iqmp != NULL) + { + BN_free(r->iqmp); + r->iqmp = iqmp; + } + + return 1; +} + +void RSA_get0_key(const RSA *r, + const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) +{ + if (n != NULL) + *n = r->n; + if (e != NULL) + *e = r->e; + if (d != NULL) + *d = r->d; +} + +void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q) +{ + if (p != NULL) + *p = r->p; + if (q != NULL) + *q = r->q; +} + +void RSA_get0_crt_params(const RSA *r, + const BIGNUM **dmp1, const BIGNUM **dmq1, + const BIGNUM **iqmp) +{ + if (dmp1 != NULL) + *dmp1 = r->dmp1; + if (dmq1 != NULL) + *dmq1 = r->dmq1; + if (iqmp != NULL) + *iqmp = r->iqmp; +} + +void DSA_get0_pqg(const DSA *d, + const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) +{ + if (p != NULL) + *p = d->p; + if (q != NULL) + *q = d->q; + if (g != NULL) + *g = d->g; +} + +int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) +{ + /* If the fields p, q and g in d are NULL, the corresponding input + * parameters MUST be non-NULL. + */ + if ((d->p == NULL && p == NULL) || (d->q == NULL && q == NULL) || (d->g == NULL && g == NULL)) + return 0; + + if (p != NULL) + { + BN_free(d->p); + d->p = p; + } + if (q != NULL) + { + BN_free(d->q); + d->q = q; + } + if (g != NULL) + { + BN_free(d->g); + d->g = g; + } + + return 1; +} + +void DSA_get0_key(const DSA *d, + const BIGNUM **pub_key, const BIGNUM **priv_key) +{ + if (pub_key != NULL) + *pub_key = d->pub_key; + if (priv_key != NULL) + *priv_key = d->priv_key; +} + +int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) +{ + /* If the field pub_key in d is NULL, the corresponding input + * parameters MUST be non-NULL. The priv_key field may + * be left NULL. + */ + if (d->pub_key == NULL && pub_key == NULL) + return 0; + + if (pub_key != NULL) + { + BN_free(d->pub_key); + d->pub_key = pub_key; + } + if (priv_key != NULL) + { + BN_free(d->priv_key); + d->priv_key = priv_key; + } + + return 1; +} + +void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) +{ + if (pr != NULL) + *pr = sig->r; + if (ps != NULL) + *ps = sig->s; +} + +int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) +{ + if (r == NULL || s == NULL) + return 0; + BN_clear_free(sig->r); + BN_clear_free(sig->s); + sig->r = r; + sig->s = s; + return 1; +} + +void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) +{ + if (pr != NULL) + *pr = sig->r; + if (ps != NULL) + *ps = sig->s; +} + +int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) +{ + if (r == NULL || s == NULL) + return 0; + BN_clear_free(sig->r); + BN_clear_free(sig->s); + sig->r = r; + sig->s = s; + return 1; +} + +void DH_get0_pqg(const DH *dh, + const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) +{ + if (p != NULL) + *p = dh->p; + if (q != NULL) + *q = dh->q; + if (g != NULL) + *g = dh->g; +} + +int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) +{ + /* If the fields p and g in d are NULL, the corresponding input + * parameters MUST be non-NULL. q may remain NULL. + */ + if ((dh->p == NULL && p == NULL) || (dh->g == NULL && g == NULL)) + return 0; + + if (p != NULL) + { + BN_free(dh->p); + dh->p = p; + } + if (q != NULL) + { + BN_free(dh->q); + dh->q = q; + } + if (g != NULL) + { + BN_free(dh->g); + dh->g = g; + } + + if (q != NULL) + { + dh->length = BN_num_bits(q); + } + + return 1; +} + +void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key) +{ + if (pub_key != NULL) + *pub_key = dh->pub_key; + if (priv_key != NULL) + *priv_key = dh->priv_key; +} + +int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) +{ + /* If the field pub_key in dh is NULL, the corresponding input + * parameters MUST be non-NULL. The priv_key field may + * be left NULL. + */ + if (dh->pub_key == NULL && pub_key == NULL) + return 0; + + if (pub_key != NULL) + { + BN_free(dh->pub_key); + dh->pub_key = pub_key; + } + if (priv_key != NULL) + { + BN_free(dh->priv_key); + dh->priv_key = priv_key; + } + + return 1; +} + +int DH_set_length(DH *dh, long length) +{ + dh->length = length; + return 1; +} + +const unsigned char *EVP_CIPHER_CTX_iv(const EVP_CIPHER_CTX *ctx) +{ + return ctx->iv; +} + +unsigned char *EVP_CIPHER_CTX_iv_noconst(EVP_CIPHER_CTX *ctx) +{ + return ctx->iv; +} +#endif + +Nan::Persistent constructor; + +/* + * Initialization and binding + */ +#define NanThrowError(err) Nan::ThrowError(err); +#define NanNewBufferHandle(length) Nan::NewBuffer(length).ToLocalChecked() +#define args info +#define NanScope() Nan::HandleScope scope +#define NanReturnUndefined() \ + { \ + info.GetReturnValue().Set(Nan::Undefined()); \ + return; \ + } +#define NanNew Nan::New +#define NanReturnValue(value) \ + { \ + info.GetReturnValue().Set(value); \ + return; \ + } +#define NanFalse() Nan::False() +#define NanTrue() Nan::True() + +#define RSA_PKCS1_SALT_LEN_HLEN -1 +#define RSA_PKCS1_SALT_LEN_MAX -2 +#define RSA_PKCS1_SALT_LEN_RECOVER -2 + +/** + * Top-level initialization function. + */ +void init(Local target) +{ + NODE_DEFINE_CONSTANT(target, RSA_NO_PADDING); + NODE_DEFINE_CONSTANT(target, RSA_PKCS1_PADDING); + NODE_DEFINE_CONSTANT(target, RSA_PKCS1_OAEP_PADDING); + NODE_DEFINE_CONSTANT(target, RSA_PKCS1_SALT_LEN_HLEN); + NODE_DEFINE_CONSTANT(target, RSA_PKCS1_SALT_LEN_MAX); + NODE_DEFINE_CONSTANT(target, RSA_PKCS1_SALT_LEN_RECOVER); + + RsaWrap::InitClass(target); + +#ifdef _WIN32 + // On Windows, we can't use Node's OpenSSL, so we link + // to a standalone OpenSSL library. Therefore, we need + // to initialize OpenSSL separately. + + //TODO: Do I need to free these? + //I'm not sure where to call ERR_free_strings() and EVP_cleanup() + OpenSSL_add_all_digests(); + OpenSSL_add_all_algorithms(); + OpenSSL_add_all_ciphers(); + ERR_load_crypto_strings(); +#endif +} + +NODE_MODULE(ursaNative, init) + +/* + * Helper functions + */ + +/** + * Schedule the current SSL error as a higher-level exception. + */ +static void scheduleSslException() +{ + char *err = ERR_error_string(ERR_get_error(), NULL); + ERR_clear_error(); + NanThrowError(err); +} + +/** + * Schedule an "allocation failed" exception. This (tries) to allocate + * as well, which very well could (probably will) fail too, but it's the + * best we can do in a bad situation. + */ +static void scheduleAllocException() +{ + NanThrowError("Allocation failed."); +} + +/** + * Convert the given (BIGNUM *) to a Buffer of unsigned big-endian + * contents. Returns a Buffer-containing handle on success. Schedules an + * exception and returns Undefined() on failure. + */ +static Nan::NAN_METHOD_RETURN_TYPE bignumToBuffer(Nan::NAN_METHOD_ARGS_TYPE args, + BIGNUM *number) +{ + int length = BN_num_bytes(number); + Local result = NanNewBufferHandle(length); + + if (BN_bn2bin(number, (unsigned char *)node::Buffer::Data(result)) < 0) + { + scheduleSslException(); + NanReturnUndefined(); + } + + NanReturnValue(result); +} + +/** + * Convert the given memory-based (BIO *) to a Buffer of its contents. + * Returns a Buffer-containing handle on success. Schedules an + * exception and returns Undefined() on failure. In either case, the + * BIO is freed by the time this function returns. + * + * As a special case to help with error handling, if given a NULL + * argument, this simply returns Undefined(). + */ +static Nan::NAN_METHOD_RETURN_TYPE bioToBuffer(Nan::NAN_METHOD_ARGS_TYPE args, + BIO *bio) +{ + if (bio == NULL) + { + NanReturnUndefined(); + } + + char *data; + long length = BIO_get_mem_data(bio, &data); + Local result = NanNewBufferHandle(length); + + if (result.IsEmpty()) + { + scheduleAllocException(); + BIO_vfree(bio); + NanReturnUndefined(); + } + + memcpy(node::Buffer::Data(result), data, length); + BIO_vfree(bio); + + NanReturnValue(result); +} + +/** + * Get a Buffer out of args[0], converted to a freshly-allocated + * memory BIO. Returns a non-null pointer on success. On failure, + * schedules an exception and returns NULL. + */ +static BIO *getArg0Bio(const Local buf) +{ + if (!node::Buffer::HasInstance(buf)) + { + NanThrowError("Expected a Buffer in args[0]."); + return NULL; + } + + char *data = node::Buffer::Data(buf); + ssize_t length = node::Buffer::Length(buf); + BIO *bio = BIO_new_mem_buf(data, length); + + if (bio == NULL) + { + scheduleSslException(); + } + + return bio; +} + +static BIGNUM *getArgXBigNum(const Local buf) +{ + if (!node::Buffer::HasInstance(buf)) + { + NanThrowError("Expected a Buffer."); + return NULL; + } + char *data = node::Buffer::Data(buf); + ssize_t length = node::Buffer::Length(buf); + + return BN_bin2bn(reinterpret_cast(data), length, NULL); +} + +/** + * Get a Buffer out of args[1], converted to a freshly-allocated (char + * *). Returns a non-null pointer on success. On failure, schedules an + * exception and returns NULL. + */ +static char *copyBufferToCharStar(const Local buf) +{ + + if (!node::Buffer::HasInstance(buf)) + { + return NULL; + } + + char *data = node::Buffer::Data(buf); + ssize_t length = node::Buffer::Length(buf); + char *result = (char *)malloc(length + 1); + + if (result == NULL) + { + scheduleAllocException(); + return NULL; + } + + memcpy(result, data, length); + result[length] = '\0'; + return result; +} + +/** + * Get a string out of args[] at the given index, converted to a + * freshly-allocated (char *). Returns a non-null pointer on + * success. On failure, schedules an exception and returns NULL. + */ +static char *copyBufferToUtf8String(const Local str) +{ + // static char *getArgString(const Arguments& args, int index) { + int length = str->Utf8Length(); + char *result = (char *)malloc(length + 1); + + if (result == NULL) + { + scheduleAllocException(); + return NULL; + } + + result[length] = 'x'; // Set up a small sanity check (see below). + str->WriteUtf8(result, length + 1); + + if (result[length] != '\0') + { + const char *message = "String conversion failed."; + NanThrowError(message); + free(result); + return NULL; + } + + return result; +} + +/** + * Generate a key, using one of the two possibly-available functions. + * This prefers the newer function, if available. + */ +static RSA *generateKey(int num, unsigned long e) +{ +#if OPENSSL_VERSION_NUMBER < 0x009080001 + return RSA_generate_key(num, e, NULL, NULL); +#else + BIGNUM *eBig = BN_new(); + + if (eBig == NULL) + { + return NULL; + } + + if (!BN_set_word(eBig, e)) + { + BN_free(eBig); + return NULL; + } + + RSA *result = RSA_new(); + + if (result == NULL) + { + BN_free(eBig); + return NULL; + } + + if (RSA_generate_key_ex(result, num, eBig, NULL) < 0) + { + RSA_free(result); + result = NULL; + } + + BN_free(eBig); + return result; +#endif +} + +/* + * Utility function implementation + */ + +/** + * Call the OpenSSL function OBJ_txt2nid() on the given string. + * This returns a number representing the text that, as far as I + * (danfuzz) know, is not necessarily stable across versions of + * OpenSSL, so it's only safe to use transiently. + */ +NAN_METHOD(TextToNid) +{ + NanScope(); + + if (args.Length() < 1) + { + NanThrowError("Missing args[0]."); + NanReturnUndefined(); + } + + if (!args[0]->IsString()) + { + NanThrowError("Expected a string in args[0]."); + NanReturnUndefined(); + } + + Local str = args[0].As(); + char *name = copyBufferToUtf8String(str); + if (name == NULL) + { + NanReturnUndefined(); + } + + int nid = OBJ_txt2nid(name); + free(name); + + if (nid == NID_undef) + { + scheduleSslException(); + NanReturnUndefined(); + } + + NanReturnValue(NanNew(nid)); +} + +/* + * RsaWrap implementation + */ + +/** + * Initialize the bindings for this class. + */ +void RsaWrap::InitClass(Local target) +{ + Local className = NanNew("RsaWrap").ToLocalChecked(); + + // Basic instance setup + Local tpl = NanNew(New); + + tpl->SetClassName(className); + tpl->InstanceTemplate()->SetInternalFieldCount(1); // req'd by ObjectWrap + + Nan::SetPrototypeMethod(tpl, "generatePrivateKey", GeneratePrivateKey); + Nan::SetPrototypeMethod(tpl, "getExponent", GetExponent); + Nan::SetPrototypeMethod(tpl, "getPrivateExponent", GetPrivateExponent); + Nan::SetPrototypeMethod(tpl, "getModulus", GetModulus); + Nan::SetPrototypeMethod(tpl, "getPrivateKeyPem", GetPrivateKeyPem); + Nan::SetPrototypeMethod(tpl, "getPublicKeyPem", GetPublicKeyPem); + Nan::SetPrototypeMethod(tpl, "privateDecrypt", PrivateDecrypt); + Nan::SetPrototypeMethod(tpl, "privateEncrypt", PrivateEncrypt); + Nan::SetPrototypeMethod(tpl, "publicDecrypt", PublicDecrypt); + Nan::SetPrototypeMethod(tpl, "publicEncrypt", PublicEncrypt); + Nan::SetPrototypeMethod(tpl, "setPrivateKeyPem", SetPrivateKeyPem); + Nan::SetPrototypeMethod(tpl, "setPublicKeyPem", SetPublicKeyPem); + Nan::SetPrototypeMethod(tpl, "sign", Sign); + Nan::SetPrototypeMethod(tpl, "verify", Verify); + Nan::SetPrototypeMethod(tpl, "createPrivateKeyFromComponents", CreatePrivateKeyFromComponents); + Nan::SetPrototypeMethod(tpl, "createPublicKeyFromComponents", CreatePublicKeyFromComponents); + Nan::SetPrototypeMethod(tpl, "openPublicSshKey", OpenPublicSshKey); + Nan::SetPrototypeMethod(tpl, "addPSSPadding", AddPSSPadding); + Nan::SetPrototypeMethod(tpl, "verifyPSSPadding", VerifyPSSPadding); + + // Store the constructor in the target bindings. + target->Set(NanNew("RsaWrap").ToLocalChecked(), tpl->GetFunction()); + constructor.Reset(tpl->GetFunction()); + + target->Set(NanNew("textToNid").ToLocalChecked(), Nan::New(TextToNid)->GetFunction()); +} + +/** + * Straightforward constructor. Nothing much to initialize, other than + * to ensure that our one instance variable is sanely NULLed. + */ +RsaWrap::RsaWrap() +{ + rsa = NULL; +} + +/** + * Destructor, which is called automatically via the ObjectWrap mechanism + * when the corresponding high-level object gets gc'ed. + */ +RsaWrap::~RsaWrap() +{ + if (rsa != NULL) + { + RSA_free(rsa); + } +} + +NAN_METHOD(RsaWrap::OpenPublicSshKey) +{ + NanScope(); + RsaWrap *obj = ObjectWrap::Unwrap(args.Holder()); + obj = expectUnset(obj); + + if (args.Length() < 2) + { + NanThrowError("Not enough args."); + NanReturnUndefined(); + } + + Local obj_n = args[0].As(); + Local obj_e = args[1].As(); + int n_length = node::Buffer::Length(obj_n); + int e_length = node::Buffer::Length(obj_e); + unsigned char *data_n = (unsigned char *)malloc(n_length); + unsigned char *data_e = (unsigned char *)malloc(e_length); + memcpy(data_n, node::Buffer::Data(obj_n), n_length); + memcpy(data_e, node::Buffer::Data(obj_e), e_length); + + if (obj->rsa == NULL) + { + obj->rsa = RSA_new(); + } + + obj->rsa_n = BN_new(); + obj->rsa_e = BN_new(); + + BN_bin2bn(data_n, n_length, obj->rsa_n); + BN_bin2bn(data_e, e_length, obj->rsa_e); + RSA_set0_key(obj->rsa, obj->rsa_n, obj->rsa_e, NULL); + + free(data_n); + free(data_e); + NanReturnUndefined(); +} + +/** + * Get an (RsaWrap *) out of the given arguments, expecting the + * underlying (RSA *) to be non-null and more specifically a private + * key. Returns a non-null pointer on success. On failure, schedules + * an exception and returns null. + */ +RsaWrap *RsaWrap::expectPrivateKey(RsaWrap *obj) +{ + obj = expectSet(obj); + + if (obj != NULL) { + RSA_get0_key(obj->rsa, NULL, NULL, (const BIGNUM **)&obj->rsa_d); + } + + // The "d" field should always be set on a private key and never + // set on a public key. + if ((obj == NULL) || (obj->rsa_d != NULL)) + { + return obj; + } + + NanThrowError("Expected a private key."); + return NULL; +} + +/** + * Get an (RsaWrap *) out of the given arguments, expecting the underlying + * (RSA *) to be non-null. Returns a non-null pointer on success. On failure, + * schedules an exception and returns null. + */ +RsaWrap *RsaWrap::expectSet(RsaWrap *obj) +{ + + if (obj->rsa != NULL) + { + return obj; + } + + NanThrowError("Key not yet set."); + return NULL; +} + +/** + * Get an (RsaWrap *) out of the given arguments, expecting the underlying + * (RSA *) to be null. Returns a non-null pointer on success. On failure, + * schedules an exception and returns null. + */ +RsaWrap *RsaWrap::expectUnset(RsaWrap *obj) +{ + + if (obj->rsa == NULL) + { + return obj; + } + + NanThrowError("Key already set."); + return NULL; +} + +/** + * Construct an empty instance. + */ +NAN_METHOD(RsaWrap::New) +{ + NanScope(); + + RsaWrap *obj = new RsaWrap(); + obj->Wrap(args.This()); + + NanReturnValue(args.This()); +} + +/** + * Set the underlying RSA struct to a newly-generated key pair. + */ +NAN_METHOD(RsaWrap::GeneratePrivateKey) +{ + NanScope(); + + RsaWrap *obj = ObjectWrap::Unwrap(args.Holder()); + obj = expectUnset(obj); + if (obj == NULL) + { + NanReturnUndefined(); + } + + // Sadly the change in V8 args type signature makes this messier now. + if (args.Length() < 1) + { + NanThrowError("Missing args[0]."); + NanReturnUndefined(); + } + + if (!args[0]->IsInt32()) + { + NanThrowError("Expected a 32-bit integer in args[0]."); + NanReturnUndefined(); + } + + if (args.Length() < 2) + { + NanThrowError("Missing args[1]."); + NanReturnUndefined(); + } + + if (!args[1]->IsInt32()) + { + NanThrowError("Expected a 32-bit integer in args[1]."); + NanReturnUndefined(); + } + + int modulusBits = args[0]->Uint32Value(); + int exponent = args[1]->Uint32Value(); + + // Sanity-check the arguments, since (as of this writing) OpenSSL + // either doesn't check, or at least doesn't consistently check: + // + // * The modulus bit count must be >= 512. Really, it just has to + // be a positive integer, but anything less than 512 is a + // horrendously bad idea. + // + // * The exponend must be positive and odd. + + if (modulusBits < 512) + { + NanThrowError("Expected modulus bit count >= 512."); + NanReturnUndefined(); + } + + if (exponent <= 0) + { + NanThrowError("Expected positive exponent."); + NanReturnUndefined(); + } + + if ((exponent & 1) == 0) + { + NanThrowError("Expected odd exponent."); + NanReturnUndefined(); + } + + obj->rsa = generateKey(modulusBits, (unsigned long)exponent); + + if (obj->rsa == NULL) + { + scheduleSslException(); + } + + NanReturnUndefined(); +} + +/** + * Get the public exponent of the underlying RSA object. The return + * value is a Buffer containing the unsigned number in big-endian + * order. + */ +NAN_METHOD(RsaWrap::GetExponent) +{ + NanScope(); + + RsaWrap *obj = ObjectWrap::Unwrap(args.Holder()); + obj = expectSet(obj); + if (obj == NULL) + { + NanReturnUndefined(); + } + + RSA_get0_key(obj->rsa, NULL, (const BIGNUM **)&obj->rsa_e, NULL); + bignumToBuffer(args, obj->rsa_e); +} + +/** + * Get the private exponent of the underlying RSA object. The return + * value is a Buffer containing the unsigned number in big-endian + * order. The returned exponent is not encrypted in any way, + * so this should be used with caution. + */ +NAN_METHOD(RsaWrap::GetPrivateExponent) +{ + NanScope(); + + RsaWrap *obj = ObjectWrap::Unwrap(args.Holder()); + obj = expectPrivateKey(obj); + if (obj == NULL) + { + NanReturnUndefined(); + } + + RSA_get0_key(obj->rsa, NULL, NULL, (const BIGNUM **)&obj->rsa_d); + bignumToBuffer(args, obj->rsa_d); +} + +/** + * Get the public modulus of the underlying RSA object. The return + * value is a Buffer containing the unsigned number in big-endian + * order. + */ +NAN_METHOD(RsaWrap::GetModulus) +{ + NanScope(); + + RsaWrap *obj = ObjectWrap::Unwrap(args.Holder()); + obj = expectSet(obj); + if (obj == NULL) + { + NanReturnUndefined(); + } + + RSA_get0_key(obj->rsa, (const BIGNUM **)&obj->rsa_n, NULL, NULL); + bignumToBuffer(args, obj->rsa_n); +} + +/** + * Get the private key of the underlying RSA object as a file + * in PEM format. The return value is a Buffer containing the + * file contents (in ASCII / UTF8). Note: This does not do any + * encryption of the results. + */ +NAN_METHOD(RsaWrap::GetPrivateKeyPem) +{ + NanScope(); + + RsaWrap *obj = ObjectWrap::Unwrap(args.Holder()); + obj = expectPrivateKey(obj); + + if (obj == NULL) + { + NanReturnUndefined(); + } + + BIO *bio = BIO_new(BIO_s_mem()); + if (bio == NULL) + { + scheduleSslException(); + NanReturnUndefined(); + } + + char *password = NULL; + int passwordLen = 0; + const EVP_CIPHER *cipher = NULL; + + if (args.Length() > 0) + { + Local pstr = args[0].As(); + password = copyBufferToUtf8String(pstr); + + Local cstr = args[1].As(); + char *cipherName = copyBufferToUtf8String(cstr); + cipher = EVP_get_cipherbyname(cipherName); + free(cipherName); + } + + if (password != NULL) + { + passwordLen = (int)strlen(password); + } + + if (!PEM_write_bio_RSAPrivateKey(bio, obj->rsa, + cipher, (unsigned char *)password, + passwordLen, NULL, NULL)) + { + scheduleSslException(); + BIO_vfree(bio); + free(password); + NanReturnUndefined(); + } + + free(password); + bioToBuffer(args, bio); +} + +/** + * Get the public key of the underlying RSA object as a file + * in PEM format. The return value is a Buffer containing the + * file contents (in ASCII / UTF8). + */ +NAN_METHOD(RsaWrap::GetPublicKeyPem) +{ + NanScope(); + + RsaWrap *obj = ObjectWrap::Unwrap(args.Holder()); + obj = expectSet(obj); + if (obj == NULL) + { + NanReturnUndefined(); + } + + BIO *bio = BIO_new(BIO_s_mem()); + if (bio == NULL) + { + scheduleSslException(); + NanReturnUndefined(); + } + + if (!PEM_write_bio_RSA_PUBKEY(bio, obj->rsa)) + { + scheduleSslException(); + BIO_vfree(bio); + NanReturnUndefined(); + } + + bioToBuffer(args, bio); +} + +/** + * Perform decryption on the given buffer using the RSA key, which + * must be a private key, and padding mode. + */ +NAN_METHOD(RsaWrap::PrivateDecrypt) +{ + NanScope(); + + RsaWrap *obj = ObjectWrap::Unwrap(args.Holder()); + obj = expectPrivateKey(obj); + + if (obj == NULL) + { + NanReturnUndefined(); + } + + if (args.Length() < 2) + { + NanThrowError("Not enough args."); + NanReturnUndefined(); + } + + Local buffer = args[0].As(); + if (!node::Buffer::HasInstance(buffer)) + { + NanThrowError("Expected a Buffer in args[0]."); + NanReturnUndefined(); + } + + size_t length = node::Buffer::Length(buffer); + char *data = node::Buffer::Data(buffer); + if (data == NULL) + { + NanReturnUndefined(); + } + + int rsaLength = RSA_size(obj->rsa); + VAR_ARRAY(unsigned char, buf, rsaLength); + + if (!args[1]->IsInt32()) + { + NanThrowError("Expected a 32-bit integer in args[1]."); + NanReturnUndefined(); + } + int padding = args[1]->Uint32Value(); + + int bufLength = RSA_private_decrypt(length, (unsigned char *)data, + buf, obj->rsa, padding); + + if (bufLength < 0) + { + scheduleSslException(); + NanReturnUndefined(); + } + + Local result = NanNewBufferHandle(bufLength); + memcpy(node::Buffer::Data(result), buf, bufLength); + NanReturnValue(result); +} + +/** + * Perform encryption on the given buffer using the RSA key, which + * must be private, and padding mode. + */ +NAN_METHOD(RsaWrap::PrivateEncrypt) +{ + NanScope(); + + RsaWrap *obj = ObjectWrap::Unwrap(args.Holder()); + obj = expectPrivateKey(obj); + if (obj == NULL) + { + NanReturnUndefined(); + } + + if (args.Length() < 2) + { + NanThrowError("Not enough args."); + NanReturnUndefined(); + } + + Local buffer = args[0].As(); + if (!node::Buffer::HasInstance(buffer)) + { + NanThrowError("Expected a Buffer in args[0]."); + NanReturnUndefined(); + } + size_t length = node::Buffer::Length(buffer); + char *data = node::Buffer::Data(buffer); + if (data == NULL) + { + NanReturnUndefined(); + } + + int rsaLength = RSA_size(obj->rsa); + Local result = NanNewBufferHandle(rsaLength); + + if (!args[1]->IsInt32()) + { + NanThrowError("Expected a 32-bit integer in args[1]."); + NanReturnUndefined(); + } + int padding = args[1]->Uint32Value(); + + int ret = RSA_private_encrypt(length, (unsigned char *)data, + (unsigned char *)node::Buffer::Data(result), + obj->rsa, padding); + + if (ret < 0) + { + scheduleSslException(); + NanReturnUndefined(); + } + + NanReturnValue(result); +} + +/** + * Perform decryption on the given buffer using the (public aspect of + * the) RSA key, and padding mode. + */ +NAN_METHOD(RsaWrap::PublicDecrypt) +{ + NanScope(); + + RsaWrap *obj = ObjectWrap::Unwrap(args.Holder()); + obj = expectSet(obj); + if (obj == NULL) + { + NanReturnUndefined(); + } + + if (args.Length() < 2) + { + NanThrowError("Not enough args."); + NanReturnUndefined(); + } + + Local buffer = args[0].As(); + if (!node::Buffer::HasInstance(buffer)) + { + NanThrowError("Expected a Buffer in args[0]."); + NanReturnUndefined(); + } + size_t length = node::Buffer::Length(buffer); + char *data = node::Buffer::Data(buffer); + if (data == NULL) + { + NanReturnUndefined(); + } + + int rsaLength = RSA_size(obj->rsa); + VAR_ARRAY(unsigned char, buf, rsaLength); + + if (!args[1]->IsInt32()) + { + NanThrowError("Expected a 32-bit integer in args[1]."); + NanReturnUndefined(); + } + int padding = args[1]->Uint32Value(); + + int bufLength = RSA_public_decrypt(length, (unsigned char *)data, + buf, obj->rsa, padding); + + if (bufLength < 0) + { + scheduleSslException(); + NanReturnUndefined(); + } + + Local result = NanNewBufferHandle(bufLength); + memcpy(node::Buffer::Data(result), buf, bufLength); + NanReturnValue(result); +} + +/** + * Perform encryption on the given buffer using the public (aspect of the) + * RSA key, and padding mode. + */ +NAN_METHOD(RsaWrap::PublicEncrypt) +{ + NanScope(); + + RsaWrap *obj = ObjectWrap::Unwrap(args.Holder()); + obj = expectSet(obj); + if (obj == NULL) + { + NanReturnUndefined(); + } + + if (args.Length() < 2) + { + NanThrowError("Not enough args."); + NanReturnUndefined(); + } + + Local buffer = args[0].As(); + if (!node::Buffer::HasInstance(buffer)) + { + NanThrowError("Expected a Buffer in args[0]."); + NanReturnUndefined(); + } + size_t length = node::Buffer::Length(buffer); + char *data = node::Buffer::Data(buffer); + + int rsaLength = RSA_size(obj->rsa); + Local result = NanNewBufferHandle(rsaLength); + + if (!args[1]->IsInt32()) + { + NanThrowError("Expected a 32-bit integer in args[1]."); + NanReturnUndefined(); + } + int padding = args[1]->Uint32Value(); + + int ret = RSA_public_encrypt(length, (unsigned char *)data, + (unsigned char *)node::Buffer::Data(result), + obj->rsa, padding); + + if (ret < 0) + { + scheduleSslException(); + NanReturnUndefined(); + } + + NanReturnValue(result); +} + +/** + * Sets the underlying RSA object to correspond to the given + * private key (a Buffer of PEM format data). This throws an + * exception if the underlying RSA had previously been set. + */ +NAN_METHOD(RsaWrap::SetPrivateKeyPem) +{ + NanScope(); + bool ok = true; + + if (args.Length() < 1) + { + NanThrowError("Missing args[0]."); + NanReturnUndefined(); + } + + RsaWrap *obj = ObjectWrap::Unwrap(args.Holder()); + obj = expectUnset(obj); + ok &= (obj != NULL); + + BIO *bio = NULL; + if (ok) + { + bio = getArg0Bio(args[0].As()); + ok &= (bio != NULL); + } + + Local buf = args[1].As(); + char *password = NULL; + if (ok && (args.Length() >= 2)) + { + password = copyBufferToCharStar(buf); + if (password == NULL) + { + NanThrowError("Expected a Buffer in args[1]."); + } + ok &= (password != NULL); + } + + if (ok) + { + obj->rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, 0, password); + if (obj->rsa == NULL) + { + scheduleSslException(); + } + } + + if (bio != NULL) + { + BIO_vfree(bio); + } + if (password != NULL) + { + free(password); + }; + NanReturnUndefined(); +} + +/** + * Sets the underlying RSA object to correspond to the given + * public key (a Buffer of PEM format data). This throws an + * exception if the underlying RSA had previously been set. + */ +NAN_METHOD(RsaWrap::SetPublicKeyPem) +{ + NanScope(); + + RsaWrap *obj = ObjectWrap::Unwrap(args.Holder()); + obj = expectUnset(obj); + if (obj == NULL) + { + NanReturnUndefined(); + } + + if (args.Length() < 1) + { + NanThrowError("Missing args[0]."); + NanReturnUndefined(); + } + + BIO *bio = getArg0Bio(args[0].As()); + if (bio == NULL) + { + NanReturnUndefined(); + } + + obj->rsa = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL); + + if (obj->rsa == NULL) + { + scheduleSslException(); + } + + BIO_vfree(bio); + NanReturnUndefined(); +} + +/** + * Sign the given hash data. First argument indicates what kind of hash + * was performed. Returns a Buffer object. + */ +NAN_METHOD(RsaWrap::Sign) +{ + NanScope(); + + RsaWrap *obj = ObjectWrap::Unwrap(args.Holder()); + obj = expectPrivateKey(obj); + if (obj == NULL) + { + NanReturnUndefined(); + } + + if (args.Length() < 2) + { + NanThrowError("Not enough args."); + NanReturnUndefined(); + } + + if (!args[0]->IsInt32()) + { + NanThrowError("Expected a 32-bit integer in args[0]."); + NanReturnUndefined(); + } + int nid = args[0]->Uint32Value(); + + Local buffer = args[1].As(); + if (!node::Buffer::HasInstance(buffer)) + { + NanThrowError("Expected a Buffer in args[1]."); + NanReturnUndefined(); + } + size_t dataLength = node::Buffer::Length(buffer); + char *data = node::Buffer::Data(buffer); + if (data == NULL) + { + NanReturnUndefined(); + } + + unsigned int rsaSize = (unsigned int)RSA_size(obj->rsa); + unsigned int sigLength = rsaSize; + Local result = NanNewBufferHandle(sigLength); + + int ret = RSA_sign(nid, (unsigned char *)data, dataLength, + (unsigned char *)node::Buffer::Data(result), + &sigLength, obj->rsa); + + if (ret == 0) + { + // TODO: Will this leak the result buffer? Is it going to be gc'ed? + scheduleSslException(); + NanReturnUndefined(); + } + + if (rsaSize != sigLength) + { + // Sanity check. Shouldn't ever happen in practice. + NanThrowError("Shouldn't happen."); + } + + NanReturnValue(result); +} + +/** + * Verify the signature on the given hash data. First argument indicates + * what kind of hash was performed. Throws an exception if the signature + * did not verify. + */ +NAN_METHOD(RsaWrap::Verify) +{ + NanScope(); + + RsaWrap *obj = ObjectWrap::Unwrap(args.Holder()); + obj = expectSet(obj); + if (obj == NULL) + { + NanReturnUndefined(); + } + + if (args.Length() < 3) + { + NanThrowError("Not enough args."); + NanReturnUndefined(); + } + + if (!args[0]->IsInt32()) + { + NanThrowError("Expected a 32-bit integer in args[0]."); + NanReturnUndefined(); + } + int nid = args[0]->Uint32Value(); + + Local buffer = args[1].As(); + if (!node::Buffer::HasInstance(buffer)) + { + NanThrowError("Expected a Buffer in args[1]."); + NanReturnUndefined(); + } + size_t dataLength = node::Buffer::Length(buffer); + char *data = node::Buffer::Data(buffer); + if (data == NULL) + { + NanReturnUndefined(); + } + + Local sigBuffer = args[2].As(); + if (!node::Buffer::HasInstance(sigBuffer)) + { + NanThrowError("Expected a Buffer in args[2]."); + NanReturnUndefined(); + } + size_t sigLength = node::Buffer::Length(sigBuffer); + char *sig = node::Buffer::Data(sigBuffer); + if (sig == NULL) + { + NanReturnUndefined(); + } + + int ret = RSA_verify(nid, (unsigned char *)data, dataLength, + (unsigned char *)sig, sigLength, obj->rsa); + if (ret == 0) + { + // Something went wrong; investigate! + unsigned long err = ERR_peek_error(); + int lib = ERR_GET_LIB(err); + int reason = ERR_GET_REASON(err); + if ((lib == ERR_LIB_RSA) && (reason == RSA_R_BAD_SIGNATURE)) + { + // This just means that the signature didn't match + // (as opposed to, say, a more dire failure in the library + // warranting an exception throw). + ERR_get_error(); // Consume the error (get it off the err stack). + NanReturnValue(NanFalse()); + } + scheduleSslException(); + NanReturnUndefined(); + } + + NanReturnValue(NanTrue()); +} + +/** + * Add PSS padding to a digest. First argument is digest algorithm ID, + * second is the digest, third is the salt length. + */ +NAN_METHOD(RsaWrap::AddPSSPadding) +{ + NanScope(); + + RsaWrap *obj = ObjectWrap::Unwrap(args.Holder()); + obj = expectSet(obj); + if (obj == NULL) + { + NanReturnUndefined(); + } + + if (args.Length() < 3) + { + NanThrowError("Not enough args."); + NanReturnUndefined(); + } + + if (!args[0]->IsInt32()) + { + NanThrowError("Expected a 32-bit integer in args[0]."); + NanReturnUndefined(); + } + int nid = args[0]->Uint32Value(); + const EVP_MD *Hash = EVP_get_digestbynid(nid); + if (Hash == NULL) + { + NanReturnUndefined(); + } + + Local buffer = args[1].As(); + if (!node::Buffer::HasInstance(buffer)) + { + NanThrowError("Expected a Buffer in args[1]."); + NanReturnUndefined(); + } + size_t mHashLength = node::Buffer::Length(buffer); + char *mHash = node::Buffer::Data(buffer); + if (mHash == NULL) + { + NanReturnUndefined(); + } + if (mHashLength != (size_t)EVP_MD_size(Hash)) + { + NanThrowError("Incorrect hash size."); + NanReturnUndefined(); + } + + if (!args[2]->IsInt32()) + { + NanThrowError("Expected a 32-bit integer in args[2]."); + NanReturnUndefined(); + } + int sLen = args[2]->Uint32Value(); + + unsigned int emLength = (unsigned int)RSA_size(obj->rsa); + Local EM = NanNewBufferHandle(emLength); + + int ret = RSA_padding_add_PKCS1_PSS(obj->rsa, + (unsigned char *)node::Buffer::Data(EM), + (unsigned char *)mHash, Hash, sLen); + if (ret == 0) + { + scheduleSslException(); + NanReturnUndefined(); + } + + NanReturnValue(EM); +} + +/** + * Verify a signature with PSS padding. First argument is digest algorithm ID, + * second is the digest, third is the padded digest, fourth is the salt length. + */ +NAN_METHOD(RsaWrap::VerifyPSSPadding) +{ + NanScope(); + + RsaWrap *obj = ObjectWrap::Unwrap(args.Holder()); + obj = expectSet(obj); + if (obj == NULL) + { + NanReturnUndefined(); + } + + if (args.Length() < 4) + { + NanThrowError("Not enough args."); + NanReturnUndefined(); + } + + if (!args[0]->IsInt32()) + { + NanThrowError("Expected a 32-bit integer in args[0]."); + NanReturnUndefined(); + } + int nid = args[0]->Uint32Value(); + const EVP_MD *Hash = EVP_get_digestbynid(nid); + if (Hash == NULL) + { + NanReturnUndefined(); + } + + Local buffer = args[1].As(); + if (!node::Buffer::HasInstance(buffer)) + { + NanThrowError("Expected a Buffer in args[1]."); + NanReturnUndefined(); + } + size_t mHashLength = node::Buffer::Length(buffer); + char *mHash = node::Buffer::Data(buffer); + if (mHash == NULL) + { + NanReturnUndefined(); + } + if (mHashLength != (size_t)EVP_MD_size(Hash)) + { + NanThrowError("Incorrect hash size."); + NanReturnUndefined(); + } + + Local emBuffer = args[2].As(); + if (!node::Buffer::HasInstance(emBuffer)) + { + NanThrowError("Expected a Buffer in args[2]."); + NanReturnUndefined(); + } + if (node::Buffer::Length(emBuffer) != (size_t)RSA_size(obj->rsa)) + { + NanThrowError("Incorrect encoded message size."); + NanReturnUndefined(); + } + char *EM = node::Buffer::Data(emBuffer); + if (EM == NULL) + { + NanReturnUndefined(); + } + + if (!args[3]->IsInt32()) + { + NanThrowError("Expected a 32-bit integer in args[3]."); + NanReturnUndefined(); + } + int sLen = args[3]->Uint32Value(); + + int ret = RSA_verify_PKCS1_PSS(obj->rsa, + (unsigned char *)mHash, Hash, (unsigned char *)EM, sLen); + if (ret == 0) + { + // Something went wrong; investigate! + unsigned long err = ERR_peek_error(); + int lib = ERR_GET_LIB(err); + int reason = ERR_GET_REASON(err); + if ((lib == ERR_LIB_RSA) && (reason == RSA_R_BAD_SIGNATURE)) + { + // This just means that the signature didn't match + // (as opposed to, say, a more dire failure in the library + // warranting an exception throw). + ERR_get_error(); // Consume the error (get it off the err stack). + NanReturnValue(NanFalse()); + } + scheduleSslException(); + NanReturnUndefined(); + } + + NanReturnValue(NanTrue()); +} + +NAN_METHOD(RsaWrap::CreatePrivateKeyFromComponents) +{ + RsaWrap *obj = ObjectWrap::Unwrap(args.Holder()); + obj = expectUnset(obj); + if (obj == NULL) + { + NanReturnUndefined(); + } + + if (args.Length() < 8) + { + NanThrowError("Not enough args."); + NanReturnUndefined(); + } + + obj->rsa = RSA_new(); + if (obj->rsa == NULL) + { + NanReturnUndefined(); + } + + BIGNUM *modulus = NULL; + BIGNUM *exponent = NULL; + BIGNUM *p = NULL; + BIGNUM *q = NULL; + BIGNUM *dp = NULL; + BIGNUM *dq = NULL; + BIGNUM *inverseQ = NULL; + BIGNUM *d = NULL; + + bool ok = true; + + modulus = getArgXBigNum(args[0].As()); + ok &= (modulus != NULL); + if (ok) + { + exponent = getArgXBigNum(args[1].As()); + ok &= (exponent != NULL); + } + if (ok) + { + p = getArgXBigNum(args[2].As()); + ok &= (p != NULL); + } + if (ok) + { + q = getArgXBigNum(args[3].As()); + ok &= (q != NULL); + } + if (ok) + { + dp = getArgXBigNum(args[4].As()); + ok &= (dp != NULL); + } + if (ok) + { + dq = getArgXBigNum(args[5].As()); + ok &= (dq != NULL); + } + if (ok) + { + inverseQ = getArgXBigNum(args[6].As()); + ok &= (inverseQ != NULL); + } + if (ok) + { + d = getArgXBigNum(args[7].As()); + ok &= (d != NULL); + } + + if (ok) + { + RSA_set0_key(obj->rsa, modulus, exponent, d); + RSA_set0_factors(obj->rsa, p, q); + RSA_set0_crt_params(obj->rsa, dp, dq, inverseQ); + } + else + { + if (modulus) + { + BN_free(modulus); + } + if (exponent) + { + BN_free(exponent); + } + if (p) + { + BN_free(p); + } + if (q) + { + BN_free(q); + } + if (dp) + { + BN_free(dp); + } + if (dq) + { + BN_free(dq); + } + if (inverseQ) + { + BN_free(inverseQ); + } + if (d) + { + BN_free(d); + } + } + + NanReturnUndefined(); +} + +NAN_METHOD(RsaWrap::CreatePublicKeyFromComponents) +{ + RsaWrap *obj = ObjectWrap::Unwrap(args.Holder()); + obj = expectUnset(obj); + if (obj == NULL) + { + NanReturnUndefined(); + } + + if (args.Length() < 2) + { + NanThrowError("Not enough args."); + NanReturnUndefined(); + } + + obj->rsa = RSA_new(); + if (obj->rsa == NULL) + { + NanReturnUndefined(); + } + + BIGNUM *modulus = NULL; + BIGNUM *exponent = NULL; + + bool ok = true; + + modulus = getArgXBigNum(args[0].As()); + ok &= (modulus != NULL); + if (ok) + { + exponent = getArgXBigNum(args[1].As()); + ok &= (exponent != NULL); + } + + if (ok) + { + RSA_set0_key(obj->rsa, modulus, exponent, NULL); + } + else + { + if (modulus) + { + BN_free(modulus); + } + if (exponent) + { + BN_free(exponent); + } + } + + NanReturnUndefined(); +} diff --git a/express-server/node_modules/ursa-optional/src/ursaNative.h b/express-server/node_modules/ursa-optional/src/ursaNative.h new file mode 100644 index 00000000..bbf9441d --- /dev/null +++ b/express-server/node_modules/ursa-optional/src/ursaNative.h @@ -0,0 +1,56 @@ +// Copyright 2012 The Obvious Corporation. + +#ifndef URSA_NATIVE_H +#define URSA_NATIVE_H + +#ifndef BUILDING_NODE_EXTENSION +#define BUILDING_NODE_EXTENSION +#endif +#include +#include +#include + +#include + +class RsaWrap : public node::ObjectWrap +{ +public: + static void InitClass(v8::Local target); + +protected: + RsaWrap(); + ~RsaWrap(); + + static NAN_METHOD(New); + static NAN_METHOD(GeneratePrivateKey); + static NAN_METHOD(GetExponent); + static NAN_METHOD(GetPrivateExponent); + static NAN_METHOD(GetModulus); + static NAN_METHOD(GetPrivateKeyPem); + static NAN_METHOD(GetPublicKeyPem); + static NAN_METHOD(PrivateDecrypt); + static NAN_METHOD(PrivateEncrypt); + static NAN_METHOD(PublicDecrypt); + static NAN_METHOD(PublicEncrypt); + static NAN_METHOD(SetPrivateKeyPem); + static NAN_METHOD(SetPublicKeyPem); + static NAN_METHOD(Sign); + static NAN_METHOD(Verify); + static NAN_METHOD(CreatePrivateKeyFromComponents); + static NAN_METHOD(CreatePublicKeyFromComponents); + static NAN_METHOD(OpenPublicSshKey); + static NAN_METHOD(AddPSSPadding); + static NAN_METHOD(VerifyPSSPadding); + +private: + static RsaWrap *expectPrivateKey(RsaWrap *obj); + static RsaWrap *expectSet(RsaWrap *obj); + static RsaWrap *expectUnset(RsaWrap *obj); + + BIGNUM *rsa_n, *rsa_e, *rsa_d; + RSA *rsa; +}; + +NAN_METHOD(TextToNid); + +#endif // def URSA_NATIVE_H diff --git a/express-server/node_modules/ursa-optional/test/.eslintrc.json b/express-server/node_modules/ursa-optional/test/.eslintrc.json new file mode 100644 index 00000000..6126ea07 --- /dev/null +++ b/express-server/node_modules/ursa-optional/test/.eslintrc.json @@ -0,0 +1,5 @@ +{ + "rules": { + "no-unused-vars": [2] + } +} diff --git a/express-server/node_modules/ursa-optional/test/another_zorch.pem b/express-server/node_modules/ursa-optional/test/another_zorch.pem new file mode 100644 index 00000000..f87df832 --- /dev/null +++ b/express-server/node_modules/ursa-optional/test/another_zorch.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQDhVzXvfTvYzne0gkD9FHlTYhsuB6wBUIZRNTZaai4EpKzleZbr +hq/R7M4DMA4UbiiuI68fMagcFYgUgfspDb3QBYVSRDpF0OmxGm4ww0LOjsHH/0ZQ +LnsFvbHNQcgJiYkLHQFRi9ARweuZNCRnw3fMY1GhfO5sq7J7SzAAbKQ3vwIDAQAB +AoGAOPTnMBpyZxGA1kJaFN348KeKgS71PfvRh3Mwwte1u/y3quT5zZxkkmYNiGa8 +GFPjumhQmkzd1gNnOu/DwRO1Fwbp0bfqwCLnd2Lz400ZrwN/S+hlzu+YR1rKOH7C +7q/BeAm/hGVejsmkl16WgEpkqTzo11566Gat9UWDAw7C1ZkCQQD2MkPuQH6P5hwF +sy0mr4zfA3+X0L032jyjajakgM9Zn2XnPeYL/R/Cx0h1oBke3CPrKNaRhRCrBwUz +MUx3gkm7AkEA6lBXfCfsiPWzLe6klV+vFaDl40x53AMy+pL0VE/f8GSqHwGPL1q1 +aa2AtiSCD505g6vq934V3K/KDK2THug3zQJAHnGIxOVkwRaLUIkfhDEhElK0bGl7 +fHSYGvz/VMg427RCPZ4B3Gmoi8VoyGLLuG0wY9vg7I2vyfZMRlBKTFzoEQJAIeh2 +gJUWect0npUGZEdwguTB397VU61y1yglC35zncozhEEpg2TRE/XzxmgKGlBaXl+m +pSIt773Qs3z66WIZkQJBAN4pwewrHawHa9yLH5X9zomL8yk7kboRguk2BaZND+KP +ENbnMowAligtYJ7w2KqpHZMJHwIOg8Yd2T9bPZKMW78= +-----END RSA PRIVATE KEY----- diff --git a/express-server/node_modules/ursa-optional/test/blort-pass.pem b/express-server/node_modules/ursa-optional/test/blort-pass.pem new file mode 100644 index 00000000..cabf8a33 --- /dev/null +++ b/express-server/node_modules/ursa-optional/test/blort-pass.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,0EE0329ADBEED6A1 + +CdxXjx5dnHDVa4swmD2X/Q9jsvN8Xcy8rUW7pcn7ijdn4uEpzVax9YD2Ewy9RsuS +3Qmhon6YdkjzqjShSXa4p2HXziZlZmgqxOHwUn1IxBK/Bne4WgpBWhkVmccCUaYm +rQhx7SwiqghzXXWvs/lDFjV9LdMFT1McUF7YY2jMmLgZjIsGKX0B/wBMF3E0/Zdo +9rYwelwS+ZYrQFcXxhZI8lg/KMmhgqEgRwjp+9z0j5H3e82Rs7eH68f2SFKld1ZY +3kQzHtTU8pGwdhWTSgxHmNMBWk2UV+TXhl88yZfYd0ugPZGk1luXu++MQLCktgfS +9xVpCmZyuxJgY8Trvf/Sc5fSfF/oB7/5TluTH5ap4jn1mELYnc/bPwZ79IKROlUs +LqcZYTRX46NLhNgqQlFyHCqOomxncxkdnkKE5jJ9AFheda4ZUX6ZL9KpCl4J13NG +aEr/D/8e/c7J5GZRWXu6kskWfDHDT/85Shpk32jxxN1/uugc3ENERojWLVoKggT8 +gtbOQ2hc3g5EqFkOcofrn74M4fEd5UymJVbr6rcaFoBtwMoTB38u4ILmmdEqYPhk +1YnJUSy9etN/fJhpS1sye0ic8xrY6ymsQKc2kYvKjCf34zKUNeLHE15f4++DN2nK +7ECbfBsIZcCJ/EyS+RfO2iaPlgx/J3I3IiQRlZv6zN72ZW8xDeEZUMDzTr8LO/GG +inIWEeXiq3H6Fi7lg1QkZqG5wfsMFWiaBkm5JDCtA7RyAecwaUvetXhMhycBWIrp +/BlyYV1pmGREWzJbN2DHVO8eZJKKEWqp2tCPko3U35+t6ps6OZbiuq4xL9mOaRmx +ukn8kjl1TgoQ1NBCjXEs0q01tlzMf2GoK/KQwqZmIpEJXo0eadyLok7nK11EuDGx +AQmHP8ycXJRC34rbN8HBVE2iMiSkhZGLvXpeEo7wrSM/AflkSWwAT61unpKC26EH +eClranXixvOF8c1peAIjn0eagW4rVTFfZbNDAbKwSeNQY/keSHvmOtq9AHDU8NhN +uFl5o958qkKFyp/bgHw9CfHdvtXDebMfbSekspKcYXmI46sWy73r5AmxVY1Axh4C +lqNm3sKPhQZ2LsX17yM7M1QyBjgytH8/a5ecpFyrAmiAx1BL4mU5d3KAzxCO0sQM +ZVyin3hbTBHffh5kGU5OH2xjquKqHmUZLlNhWIsfYBKdqenXBsQoGPPwL1kVNNxj +uP4AB0Xk/BUIVvKsNfcCTr0iP8YtVXYW4jD0Y+OtoLHc6e4vLUW15cYJZIYfg9zf +5rwY8MaP2XTcJovNIsKoyEYxfnMmrlTIbaT0H7JE4nbWx4nnR7X6ybk7KbuS4dVJ +uNswQWQr6WJ29kvv4pvNCKAEPXyTQeIWw9bG8ETB7xuDXgzHJkXZPhs4vGOqTxpf +JkeJtR61rnoqFBEhncHMdF9c5fTSZRcYtTt6miNc6CYJs5tdQvY82XN4H/adqghI +NN/bqFAxLxA4RoXmibIybt+IEf2ejCl2xfWPs9ejnctYL+5JLFT4+IpOQDh/3rtG +fSKhaigLCt7yprOsAxxGg/OF6I6gwNgfeujApoTQIgq0X/frF2YvjP7xNLw8oNeU +-----END RSA PRIVATE KEY----- diff --git a/express-server/node_modules/ursa-optional/test/blort.pem b/express-server/node_modules/ursa-optional/test/blort.pem new file mode 100644 index 00000000..89f02ccb --- /dev/null +++ b/express-server/node_modules/ursa-optional/test/blort.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEArgov0KHVYlOtS15/WIO0Hpz9NIuWQiH/9VuCqjEnsMJdZR20 +NsxiNCjMTjOXtl8jCGFAp8fyb5peT7Qlp4xZky6odeyFEc6Z9QInyRSVBozlRoYS +hefQ6JSPFaF9k+FYFN/xz0LYHZwZCW+r78dQV9ZGKBQT61El8NiriiqKq1SBZiEI +7jT18J0i6H1qFVAkkZcyz3v85/yudPUC1wBFwzfk9yJ9O8bpNlGonxlDoQKXxHS8 +yV15dTqAAoeVysBqQk1/NiDQuEJMbrq3cfDll0scsnVec0dwIUNY9UasxrbPpwk0 +0ce54uWjwYl/sQ+AOvKZhJXbJFEfKyFi8f2EdQIDAQABAoIBADZx7V9hITXvY2kO +mNwB55kkF3oWqNzrcf05sXi4g+giBcGaN0RlT9ttX+ye6zkcLgNzGRzjyg3rxtE8 +VANEPslycTTi1wYpEbS6BeQ70hsIfLlBPA4z5QC9aL2llXlrp3hwTl8+VAl/Sb3P +94O9YH76A1yKW2jkK/Bad99zS4opEvKRaBdMN3epphrUaUbseCckrgQp5/JVxSLm +0/rQ7fFhGjiTbn7YdMHLzDkESqUqVdpuU7XQYupb3xiLlHMthgNRzhkrPEHOlcyy +l5WIxP5mEoBbIc1WteiwgYkPhHpGFSXkXmsnmuqpI504JXvWyOZ0CVLBpcg1+YOl +9JG9askCgYEA5sSIz8Z8AJ2uQ4sWfP44kfd2kSFPcEY8ehyRewR+qOtA1S9Jni0y +5BSYUP3a6Z8eolj70SAVY68WQ1HHVyzPv84RRKYRUiMQPccUZbTjLYtX+fGjriQc +EhchV0ZHSweCsu5S0LdZtcWIF2t4Kq+6fLD8aFjfv5KgzkP5/EhoDNsCgYEAwRHF +CrijUmzqjhielwp72frwJOdjdsb9RT5kZMOvlCyPpxjdTZwW3AXScKrzotYAFzlS +70FxIcB2ewStZwObMVk91ZWDU8QI4aMf6P/aN7hNILmbPsZ8HXEEYrWzxNFtTtfP +YqLCDMbuvSEaQ3/K+lVU3j/6OlAWVbo72fFBzO8CgYEAuIC+GdFJ53wqjhowWrMv +K5U9GQAW8V9WjxM0RbTsR8X/yfLK20qr+6tztJ2iX1M3PPoEK8mJEHA2TpCd3lcX +qvTo3YghJRifraTz6/VaBVn5dv75rQt13gjcQVkROy3AE6t0Tyeo9CoAiykDpK1n +XrZquEsGabakFwZGYqzJdC0CgYBv4zhpyi78KZqU1rexmKXF4aMh/+aogxFr+4h6 +zN0H5fsqP0KhI4Ar6kPWf3vKNnK/Ar2JYkeJ49vF1yQWuwRJSQqIqKj+9nCfMsXf +Zca02932xRmu+6AZ/9Em015nBWdvdan944zJks/wUyrBS2H6SVFxq2n8OUV4UQE2 +gJY9iQKBgQDazbQaXKDuJDHTMsvZfIXdhXC0vbWb5P0TJ0lUz5lN5dfLxVj/MyCS +7Es98RTf+4wcBMBUDO5Qs5/2Wv0ZSkb2SCJ73Tvs7cnJZwY7MpY53wvhr4jIjAog +DdvScUn3F/qn8sURn0uu9Kz9fqrC/tZeANU6cpBBtWykTLb/spmwuQ== +-----END RSA PRIVATE KEY----- diff --git a/express-server/node_modules/ursa-optional/test/blort.pub b/express-server/node_modules/ursa-optional/test/blort.pub new file mode 100644 index 00000000..8ee3054d --- /dev/null +++ b/express-server/node_modules/ursa-optional/test/blort.pub @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArgov0KHVYlOtS15/WIO0 +Hpz9NIuWQiH/9VuCqjEnsMJdZR20NsxiNCjMTjOXtl8jCGFAp8fyb5peT7Qlp4xZ +ky6odeyFEc6Z9QInyRSVBozlRoYShefQ6JSPFaF9k+FYFN/xz0LYHZwZCW+r78dQ +V9ZGKBQT61El8NiriiqKq1SBZiEI7jT18J0i6H1qFVAkkZcyz3v85/yudPUC1wBF +wzfk9yJ9O8bpNlGonxlDoQKXxHS8yV15dTqAAoeVysBqQk1/NiDQuEJMbrq3cfDl +l0scsnVec0dwIUNY9UasxrbPpwk00ce54uWjwYl/sQ+AOvKZhJXbJFEfKyFi8f2E +dQIDAQAB +-----END PUBLIC KEY----- diff --git a/express-server/node_modules/ursa-optional/test/blort.sshpub b/express-server/node_modules/ursa-optional/test/blort.sshpub new file mode 100644 index 00000000..cc11928c --- /dev/null +++ b/express-server/node_modules/ursa-optional/test/blort.sshpub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCuCi/QodViU61LXn9Yg7QenP00i5ZCIf/1W4KqMSewwl1lHbQ2zGI0KMxOM5e2XyMIYUCnx/Jvml5PtCWnjFmTLqh17IURzpn1AifJFJUGjOVGhhKF59DolI8VoX2T4VgU3/HPQtgdnBkJb6vvx1BX1kYoFBPrUSXw2KuKKoqrVIFmIQjuNPXwnSLofWoVUCSRlzLPe/zn/K509QLXAEXDN+T3In07xuk2UaifGUOhApfEdLzJXXl1OoACh5XKwGpCTX82INC4Qkxuurdx8OWXSxyydV5zR3AhQ1j1RqzGts+nCTTRx7ni5aPBiX+xD4A68pmEldskUR8rIWLx/YR1 diff --git a/express-server/node_modules/ursa-optional/test/fixture.js b/express-server/node_modules/ursa-optional/test/fixture.js new file mode 100644 index 00000000..23d94ccf --- /dev/null +++ b/express-server/node_modules/ursa-optional/test/fixture.js @@ -0,0 +1,215 @@ +// Copyright 2012 The Obvious Corporation. + +/* + * Common fixture for use across tests + */ + +/* + * Modules used + */ + +"use strict"; + +var fs = require("fs"); + +var ursa = require("../lib/ursa"); +var ursaNative = require("bindings")("ursaNative"); + + +/* + * Variable definitions + */ + +var BASE64 = "base64"; +var BINARY = "binary"; +var HEX = "hex"; +var SHA1 = "sha1"; +var SHA256 = "sha256"; +var UTF8 = "utf8"; +var DES_EDE3_CBC = "des-ede3-cbc"; + +var PASS_PRIVATE_KEY = fs.readFileSync(__dirname + "/blort-pass.pem"); +var PRIVATE_KEY = fs.readFileSync(__dirname + "/blort.pem"); +var PUBLIC_KEY = fs.readFileSync(__dirname + "/blort.pub"); +var SSH_PUBLIC_KEY_FILE = fs.readFileSync(__dirname + "/blort.sshpub"); +var PRIVATE_KEY_2 = fs.readFileSync(__dirname + "/zorch.pem"); +var PUBLIC_KEY_2 = fs.readFileSync(__dirname + "/zorch.pub"); +var PRIVATE_KEY_2 = fs.readFileSync(__dirname + "/zorch.pem"); +var PRIVATE_KEY_3 = fs.readFileSync(__dirname + "/another_zorch.pem"); + +var PASSWORD = new Buffer("biscuits", UTF8); + +var EXPONENT_HEX = "010001"; +var MODULUS_HEX = + "ae0a2fd0a1d56253ad4b5e7f5883b41e9cfd348b964221fff55b82aa3127b0c2" + + "5d651db436cc623428cc4e3397b65f23086140a7c7f26f9a5e4fb425a78c5993" + + "2ea875ec8511ce99f50227c91495068ce546861285e7d0e8948f15a17d93e158" + + "14dff1cf42d81d9c19096fabefc75057d646281413eb5125f0d8ab8a2a8aab54" + + "81662108ee34f5f09d22e87d6a155024919732cf7bfce7fcae74f502d70045c3" + + "37e4f7227d3bc6e93651a89f1943a10297c474bcc95d79753a80028795cac06a" + + "424d7f3620d0b8424c6ebab771f0e5974b1cb2755e734770214358f546acc6b6" + + "cfa70934d1c7b9e2e5a3c1897fb10f803af2998495db24511f2b2162f1fd8475"; + +var PLAINTEXT = "Muffins are tasty."; +var PLAINTEXT_PADDED = + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + "Muffins are tasty."; +var PRIVATE_CIPHERTEXT_HEX = + "98a96084dc8dfad2c4e604dc20def71acbf784b8b34ecafeb2840e238ac8031c" + + "7559004fa8337d20889b8a582af4f7d3707ab41d0a81487f0d80fb82be49537c" + + "2b9cd8dbb3b772fe0306ff9b4b99faa7cc26d5c04b1e8e79505bac1e8f2cdad2" + + "d3d8680eee3c16db8742b61935fca9679070d278f988ce4d414ab49a544c9088" + + "17a0d340a41384f4b8d826e41031ddcd3f72c29dec2fee0355a8203ea0d381a1" + + "a0f0969804d4968fb2e6220db5cf02e2c2200ff9d0a5a5037ac859a55c005ecc" + + "52ce194a6a9624c71547c96cf90d911caa4097f9cdfded71d23c9f8f5551188c" + + "8326357d54224ab25b9f29c1efdbc960a0968e4c9027cd507ffadd8dff93256c"; +var PRIVATE_OLD_PAD_CIPHER_HEX = + "69d1c385929fc00f89aa98ae9cd8529afe884b581505acdcd4ceaa10bfda9adc" + + "79c472dd7e35bcc94f1146459c6a8d96e572116c7a62f1da5dd18cdb8f81e72b" + + "4a4649f40470e88c11b04fdf72e48c6adb44c41edc0c4c56074a041c03017f72" + + "f66a000066a4dbe888119c83f79e7cb8f667f0af1af41cf4adf21320fada9355" + + "6d056a2fdb1f5a9f5708e096a7408a115efa14f0e2f94feaa32322aa4af9c97a" + + "438d205f62317020e657c5057227a3d7e60a6a6658781cf41b0820988a4f9e8e" + + "b947c424248d231c3e43c711b0c4a4342a0fa484d0e3ded231a695250f4dafcf" + + "f9e94d02e3f74d4c509cfae24b8615e619805c9cdc9e85faed7d706dd6891383"; +var PUBLIC_CIPHERTEXT_HEX = + "16b5e95a02db09e95bb5419998b3c5f450571578be271602828740242236e6aa" + + "0bce325d6b9a681038c864e0877a3e68e20329a3602829128385f182a20f06c7" + + "6f4c82f4f58481ff19ac2db9fd2b6b097047f741fa81a6c6a50b33259f3458b7" + + "5adcc40cc7ce71654d69936f1f77bdc684d069615ffeb71566487cdd62c55bc9" + + "5688452cb1857c91fd6cc0c7506f974ff4274a88b768f5e332b64933cabc9ef5" + + "2204e62f8682c177d5c7aa6e94e66125ad7a42eb9352e6af1ea6478e92599454" + + "65bc54fed2b45317713f7caa98cbd28a14c4c7fabe8689e735985e3fa6bd7ca8" + + "bda58bee1b3cba48cb0d1508c79c23d48413b3dc296aabf5291288783ff037ef"; +var PUBLIC_CIPHERTEXT_NP_HEX = + "51b965fd83d619f9c3fec28330c7564c90439da62ec962f0c22df2e8e5bf9e52" + + "712755d4bb004a0dcfd8e6e0acc92553805c11158b3e36a3f74d4da6574514e8" + + "10313bcbe601fe43c7bb74872ab1a252ea78db775175662ed20baf05e870a265" + + "1a06afdec90e9bd7a21cba0282ae0ca07e82898bcfbcc162d4f6780f5db89216" + + "7a85bb5d26afc7551f356b054bb1ebb312fa02e212b2d0a751964a6ca790d6dd" + + "424df1beb5e7887ae8498070955ba65777b02c7e47ebbfdfc81a54b6fa506869" + + "29cf603b19cbaf1f32ad795ee8b6619b3dd8764626483425334cc892afc9e6e2" + + "ca371a850ae29336f559da16acc250600febcbd57524ccc0f181c995ce3f74ba"; +var PLAINTEXT_SHA256 = + "44d7b7069244377863405b7c6a8c1e0fde6c68f02631668e41de3e9503429dcb"; +var PLAINTEXT_SHA256_SIGNATURE = + "98349f92a91a2de46a897901a54b395a85fb618ac904d3d01d3c37d54fbdaba5" + + "f2f17fbcd45b9237b0b2f63398d5ab113c67cf3a356d30a14eeff9b53b0e7bef" + + "8b347d835cb60550b082d86293f5fb3354a1d6d85ff19f1c6696683dc3ff55d6" + + "72b88f3d365b0d56a65e3f974a795feee84b2097646673ccb4336950c04a3ba9" + + "bd189c9ae03ee824bd5a70a5c40c6ea0b124f4256a18a054d175e339c0f4fdfd" + + "32edacdec17940343889b2f940edf10c9da338db59972735049eea77632ff895" + + "53d42ded904959718c9cf5e43a50a315ab860be64d0bd4ef69bd01154d2108a9" + + "5127b0de26318d8b0c87eace03502c0cbfbe4683c5da7cf30bce3a386534b302"; + +var SSH_PUBLIC_KEY = + new Buffer(SSH_PUBLIC_KEY_FILE.toString(UTF8).slice(8), BASE64); +var SSH_PUBLIC_KEY_FINGERPRINT_HEX = "e7738e886aaf6f0301d62d459a892dc3"; + +var FAKE_SHA256_TO_SIGN = + "0123456789abcdef00112233445566778899aabbccddeeff9876543210fedcba"; +var FAKE_SHA256_SIGNATURE = + "023fad1e5a94d417fc81ef477cc307578451791a87458794f993b9c8acd680aa" + + "0458532349fafec4df9351f6962b656b6c71fe977ec9d9c4cc2956a0d22ab9c8" + + "3a3639148d0bfe2a1d606868bee0b5a0c0d7b2bfaf80d4ed35d31f22733812dd" + + "454e8beb119c935f250000f44eeefd61d45bffb3aa42bcb8be6eb5331dc83a14" + + "bfc4df1dd2120f1d1b8539bd28cd4ebb6f3cf9439279278f5d472b75bff73c1b" + + "9b7cf713f311e3e25d7b0bfa0ee25f25f78c06335d8440e6a96318d0246c1581" + + "31c351b661694cfd688cd12f16db60ca496ca75338830d98dd1545ca835832d0" + + "15398a8dbc55eccb5c95fc9e825960ebd99b9b614e18fe0284a2def94cfe9aba"; + +var PRIVATE_KEY_COMPONENTS = { + modulus: new Buffer('4Vc173072M53tIJA/RR5U2IbLgesAVCGUTU2WmouBKSs5XmW64av0ezOAzAOFG4oriOvHzGoHBWIFIH7KQ290AWFUkQ6RdDpsRpuMMNCzo7Bx/9GUC57Bb2xzUHICYmJCx0BUYvQEcHrmTQkZ8N3zGNRoXzubKuye0swAGykN78=', 'base64'), + exponent: new Buffer('AQAB', 'base64'), + p: new Buffer('9jJD7kB+j+YcBbMtJq+M3wN/l9C9N9o8o2o2pIDPWZ9l5z3mC/0fwsdIdaAZHtwj6yjWkYUQqwcFMzFMd4JJuw==', 'base64'), + q: new Buffer('6lBXfCfsiPWzLe6klV+vFaDl40x53AMy+pL0VE/f8GSqHwGPL1q1aa2AtiSCD505g6vq934V3K/KDK2THug3zQ==', 'base64'), + dp: new Buffer('HnGIxOVkwRaLUIkfhDEhElK0bGl7fHSYGvz/VMg427RCPZ4B3Gmoi8VoyGLLuG0wY9vg7I2vyfZMRlBKTFzoEQ==', 'base64'), + dq: new Buffer('Ieh2gJUWect0npUGZEdwguTB397VU61y1yglC35zncozhEEpg2TRE/XzxmgKGlBaXl+mpSIt773Qs3z66WIZkQ==', 'base64'), + inverseQ: new Buffer('3inB7CsdrAdr3Isflf3OiYvzKTuRuhGC6TYFpk0P4o8Q1ucyjACWKC1gnvDYqqkdkwkfAg6Dxh3ZP1s9koxbvw==', 'base64'), + d: new Buffer('OPTnMBpyZxGA1kJaFN348KeKgS71PfvRh3Mwwte1u/y3quT5zZxkkmYNiGa8GFPjumhQmkzd1gNnOu/DwRO1Fwbp0bfqwCLnd2Lz400ZrwN/S+hlzu+YR1rKOH7C7q/BeAm/hGVejsmkl16WgEpkqTzo11566Gat9UWDAw7C1Zk=', 'base64'), +}; + +// From ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip + +var PSS_MODULUS_HEX = + "a2ba40ee07e3b2bd2f02ce227f36a195024486e49c19cb41bbbdfbba98b22b0e"+ + "577c2eeaffa20d883a76e65e394c69d4b3c05a1e8fadda27edb2a42bc000fe88"+ + "8b9b32c22d15add0cd76b3e7936e19955b220dd17d4ea904b1ec102b2e4de775"+ + "1222aa99151024c7cb41cc5ea21d00eeb41f7c800834d2c6e06bce3bce7ea9a5"; + +var PSS_M_HEX = + "859eef2fd78aca00308bdc471193bf55bf9d78db8f8a672b484634f3c9c26e64"+ + "78ae10260fe0dd8c082e53a5293af2173cd50c6d5d354febf78b26021c25c027"+ + "12e78cd4694c9f469777e451e7f8e9e04cd3739c6bbfedae487fb55644e9ca74"+ + "ff77a53cb729802f6ed4a5ffa8ba159890fc"; + +var PSS_MHASH_HEX = + "37b66ae0445843353d47ecb0b4fd14c110e62d6a"; + +var PSS_EM_HEX = + "66e4672e836ad121ba244bed6576b867d9a447c28a6e66a5b87dee7fbc7e65af" + + "5057f86fae8984d9ba7f969ad6fe02a4d75f7445fefdd85b6d3a477c28d24ba1" + + "e3756f792dd1dce8ca94440ecb5279ecd3183a311fc896da1cb39311af37ea4a" + + "75e24bdbfd5c1da0de7cecdf1a896f9d8bc816d97cd7a2c43bad546fbe8cfebc"; + +var PSS_S_HEX = + "8daa627d3de7595d63056c7ec659e54406f10610128baae821c8b2a0f3936d54" + + "dc3bdce46689f6b7951bb18e840542769718d5715d210d85efbb596192032c42" + + "be4c29972c856275eb6d5a45f05f51876fc6743deddd28caec9bb30ea99e02c3" + + "488269604fe497f74ccd7c7fca1671897123cbd30def5d54a2b5536ad90a747e"; + +var PSS_PUBLIC_KEY = fs.readFileSync(__dirname + "/pss_tv.pub"); + +/* + * Exported bindings + */ + +module.exports = { + BASE64: BASE64, + BINARY: BINARY, + HEX: HEX, + SHA1: SHA1, + SHA256: SHA256, + UTF8: UTF8, + DES_EDE3_CBC: DES_EDE3_CBC, + + EXPONENT_HEX: EXPONENT_HEX, + FAKE_SHA256_TO_SIGN: FAKE_SHA256_TO_SIGN, + FAKE_SHA256_SIGNATURE: FAKE_SHA256_SIGNATURE, + MODULUS_HEX: MODULUS_HEX, + PASSWORD: PASSWORD, + PASS_PRIVATE_KEY: PASS_PRIVATE_KEY, + PLAINTEXT: PLAINTEXT, + PLAINTEXT_PADDED: PLAINTEXT_PADDED, + PLAINTEXT_SHA256: PLAINTEXT_SHA256, + PLAINTEXT_SHA256_SIGNATURE: PLAINTEXT_SHA256_SIGNATURE, + PRIVATE_CIPHERTEXT_HEX: PRIVATE_CIPHERTEXT_HEX, + PRIVATE_OLD_PAD_CIPHER_HEX: PRIVATE_OLD_PAD_CIPHER_HEX, + PRIVATE_KEY: PRIVATE_KEY, + PRIVATE_KEY_2: PRIVATE_KEY_2, + PRIVATE_KEY_3: PRIVATE_KEY_3, + PUBLIC_CIPHERTEXT_HEX: PUBLIC_CIPHERTEXT_HEX, + PUBLIC_CIPHERTEXT_NP_HEX: PUBLIC_CIPHERTEXT_NP_HEX, + PUBLIC_KEY: PUBLIC_KEY, + PUBLIC_KEY_2: PUBLIC_KEY_2, + SSH_PUBLIC_KEY: SSH_PUBLIC_KEY, + SSH_PUBLIC_KEY_FINGERPRINT_HEX: SSH_PUBLIC_KEY_FINGERPRINT_HEX, + PRIVATE_KEY_COMPONENTS: PRIVATE_KEY_COMPONENTS, + PSS_MODULUS_HEX: PSS_MODULUS_HEX, + PSS_M_HEX: PSS_M_HEX, + PSS_MHASH_HEX: PSS_MHASH_HEX, + PSS_EM_HEX: PSS_EM_HEX, + PSS_S_HEX: PSS_S_HEX, + PSS_PUBLIC_KEY: PSS_PUBLIC_KEY, + + RsaWrap: ursaNative.RsaWrap, + + ursa: ursa, + ursaNative: ursaNative +}; diff --git a/express-server/node_modules/ursa-optional/test/native.js b/express-server/node_modules/ursa-optional/test/native.js new file mode 100644 index 00000000..a6b8b833 --- /dev/null +++ b/express-server/node_modules/ursa-optional/test/native.js @@ -0,0 +1,752 @@ +// Copyright 2012 The Obvious Corporation. + +/* + * Tests of the underlying RsaWrap class. + */ + +/* + * Modules used + */ + +"use strict"; + +var assert = require("assert"); + +var fixture = require("./fixture"); +var RsaWrap = fixture.RsaWrap; +var ursaNative = fixture.ursaNative; +var textToNid = ursaNative.textToNid; +var nodeVersion = Number(process.version.match(/^v(\d+\.\d+)/)[1]); + +/** + * Asserts that two strings are equal, ignoring Windows newline differences + */ +function assertStringEqual(actual, expected, message) { + assert.equal(actual.replace(/\r\n/g, '\n'), expected.replace(/\r\n/g, '\n'), message); +} + +describe('native', function() { + it('new', function() { + new RsaWrap(); + }); + + it('setPrivateKeyPem', function() { + var rsa = new RsaWrap(); + rsa.setPrivateKeyPem(fixture.PRIVATE_KEY); + + rsa = new RsaWrap(); + rsa.setPrivateKeyPem(fixture.PASS_PRIVATE_KEY, fixture.PASSWORD); + }); + + it('fail_setPrivateKeyPem', function() { + var rsa = new RsaWrap(); + + function f1() { + rsa.setPrivateKeyPem(); + } + assert.throws(f1, /Missing args\[0]\./); + + function f2() { + rsa.setPrivateKeyPem("x"); + } + assert.throws(f2, /Expected a Buffer in args\[0]\./); + + function f3() { + rsa.setPrivateKeyPem(new Buffer("x")); + } + assert.throws(f3, /no start line/); + + function f4() { + rsa.setPrivateKeyPem(fixture.PASS_PRIVATE_KEY, undefined); + } + assert.throws(f4, /Expected a Buffer in args\[1]\./); + + function f5() { + rsa.setPrivateKeyPem(fixture.PASS_PRIVATE_KEY, "x"); + } + assert.throws(f5, /Expected a Buffer in args\[1]\./); + + function f6() { + rsa.setPrivateKeyPem(fixture.PASS_PRIVATE_KEY, + new Buffer("INCORRECT PASS")); + } + assert.throws(f6, /bad decrypt/); + + // Check for "set once." + function f7() { + rsa.setPrivateKeyPem(fixture.PRIVATE_KEY); + } + f7(); + assert.throws(f7, /Key already set\./); + }); + + it('setPublicKeyPem', function() { + var rsa = new RsaWrap(); + rsa.setPublicKeyPem(fixture.PUBLIC_KEY); + }); + + it('fail_setPublicKeyPem', function() { + var rsa = new RsaWrap(); + + function f1() { + rsa.setPublicKeyPem(); + } + assert.throws(f1, /Missing args\[0]\./); + + function f2() { + rsa.setPublicKeyPem("x"); + } + assert.throws(f2, /Expected a Buffer in args\[0]\./); + + function f3() { + rsa.setPublicKeyPem(new Buffer("x")); + } + assert.throws(f3, /no start line/); + + // Check for "set once." + function f4() { + rsa.setPublicKeyPem(fixture.PUBLIC_KEY); + } + f4(); + assert.throws(f4, /Key already set\./); + }); + + it('getExponent', function() { + var rsa = new RsaWrap(); + rsa.setPublicKeyPem(fixture.PUBLIC_KEY); + var value = rsa.getExponent().toString(fixture.HEX); + assert.equal(value, fixture.EXPONENT_HEX); + + rsa = new RsaWrap(); + rsa.setPrivateKeyPem(fixture.PRIVATE_KEY); + value = rsa.getExponent().toString(fixture.HEX); + assert.equal(value, fixture.EXPONENT_HEX); + }); + + it('fail_getExponent', function() { + var rsa = new RsaWrap(); + + function f1() { + rsa.getExponent(); + } + assert.throws(f1, /Key not yet set\./); + }); + + it('getModulus', function() { + var rsa = new RsaWrap(); + rsa.setPublicKeyPem(fixture.PUBLIC_KEY); + var value = rsa.getModulus().toString(fixture.HEX); + assert.equal(value, fixture.MODULUS_HEX); + + rsa = new RsaWrap(); + rsa.setPrivateKeyPem(fixture.PRIVATE_KEY); + value = rsa.getModulus().toString(fixture.HEX); + assert.equal(value, fixture.MODULUS_HEX); + }); + + it('fail_getModulus', function() { + var rsa = new RsaWrap(); + + function f1() { + rsa.getModulus(); + } + assert.throws(f1, /Key not yet set\./); + }); + + it('getPrivateExponent', function() { + var rsa = new RsaWrap(); + rsa.createPrivateKeyFromComponents( + fixture.PRIVATE_KEY_COMPONENTS.modulus, + fixture.PRIVATE_KEY_COMPONENTS.exponent, + fixture.PRIVATE_KEY_COMPONENTS.p, + fixture.PRIVATE_KEY_COMPONENTS.q, + fixture.PRIVATE_KEY_COMPONENTS.dp, + fixture.PRIVATE_KEY_COMPONENTS.dq, + fixture.PRIVATE_KEY_COMPONENTS.inverseQ, + fixture.PRIVATE_KEY_COMPONENTS.d); + + var value = rsa.getPrivateExponent(); + assert.equal(value.toString(fixture.HEX), fixture.PRIVATE_KEY_COMPONENTS.d.toString(fixture.HEX)); + }); + + it('getPrivateKeyPem', function() { + var keyStr = fixture.PRIVATE_KEY.toString(fixture.UTF8); + + var rsa = new RsaWrap(); + rsa.setPrivateKeyPem(fixture.PRIVATE_KEY); + + var pem = rsa.getPrivateKeyPem().toString(fixture.UTF8); + assertStringEqual(pem, keyStr); + }); + + it.skip('getPrivateKeyPemWithPassPhrase', function() { + var keyStr = fixture.PASS_PRIVATE_KEY.toString(fixture.UTF8); + + var rsa = new RsaWrap(); + rsa.setPrivateKeyPem(fixture.PASS_PRIVATE_KEY, fixture.PASSWORD); + + var pem = rsa.getPrivateKeyPem(fixture.PASSWORD, fixture.DES_EDE3_CBC).toString(fixture.UTF8); + assertStringEqual(pem, keyStr); + }) + + it('fail_getPrivateKeyPem', function() { + var rsa = new RsaWrap(); + + function f1() { + rsa.getPrivateKeyPem(); + } + + assert.throws(f1, /Key not yet set\./); + rsa.setPublicKeyPem(fixture.PUBLIC_KEY); + assert.throws(f1, /Expected a private key\./); + }); + + it('getPublicKeyPem', function() { + var keyStr = fixture.PUBLIC_KEY.toString(fixture.UTF8); + + var rsa = new RsaWrap(); + rsa.setPublicKeyPem(fixture.PUBLIC_KEY); + var pem = rsa.getPublicKeyPem().toString(fixture.UTF8); + assertStringEqual(pem, keyStr); + + rsa = new RsaWrap(); + rsa.setPrivateKeyPem(fixture.PRIVATE_KEY); + pem = rsa.getPublicKeyPem().toString(fixture.UTF8); + assertStringEqual(pem, keyStr); + }); + + it('fail_getPublicKeyPem', function() { + var rsa = new RsaWrap(); + + function f1() { + rsa.getPublicKeyPem(); + } + assert.throws(f1, /Key not yet set\./); + }); + + it('privateDecrypt', function() { + var rsa = new RsaWrap(); + rsa.setPrivateKeyPem(fixture.PRIVATE_KEY); + + var encoded = new Buffer(fixture.PRIVATE_CIPHERTEXT_HEX, fixture.HEX); + var decoded = rsa.privateDecrypt(encoded, ursaNative.RSA_PKCS1_OAEP_PADDING).toString(fixture.UTF8); + assert.equal(decoded, fixture.PLAINTEXT); + + encoded = new Buffer(fixture.PRIVATE_OLD_PAD_CIPHER_HEX, fixture.HEX); + decoded = rsa.privateDecrypt(encoded, ursaNative.RSA_PKCS1_PADDING).toString(fixture.UTF8); + assert.equal(decoded, fixture.PLAINTEXT); + }); + + it('fail_privateDecrypt', function() { + var rsa = new RsaWrap(); + + function f1() { + rsa.privateDecrypt(); + } + + assert.throws(f1, /Key not yet set\./); + rsa.setPublicKeyPem(fixture.PUBLIC_KEY); + assert.throws(f1, /Expected a private key\./); + + rsa = new RsaWrap(); + rsa.setPrivateKeyPem(fixture.PRIVATE_KEY); + + function f2() { + rsa.privateDecrypt("x", ursaNative.RSA_PKCS1_OAEP_PADDING); + } + assert.throws(f2, /Expected a Buffer in args\[0]\./); + + function f3() { + rsa.privateDecrypt(new Buffer("x"), ursaNative.RSA_PKCS1_OAEP_PADDING); + } + assert.throws(f3, /decoding error/); + + function f4() { + rsa.privateDecrypt(new Buffer("x"), "str"); + } + assert.throws(f4, /Expected a 32-bit integer/); + }); + + it('publicEncrypt', function() { + // No other reasonable way to test this than to do a round trip. + var plainBuf = new Buffer(fixture.PLAINTEXT, fixture.UTF8); + var priv = new RsaWrap(); + priv.setPrivateKeyPem(fixture.PRIVATE_KEY); + + var rsa = new RsaWrap(); + rsa.setPublicKeyPem(fixture.PUBLIC_KEY); + var encoded = rsa.publicEncrypt(plainBuf, ursaNative.RSA_PKCS1_OAEP_PADDING); + var decoded = priv.privateDecrypt(encoded, ursaNative.RSA_PKCS1_OAEP_PADDING).toString(fixture.UTF8); + assert.equal(decoded, fixture.PLAINTEXT); + + encoded = priv.publicEncrypt(plainBuf, ursaNative.RSA_PKCS1_OAEP_PADDING); + decoded = priv.privateDecrypt(encoded, ursaNative.RSA_PKCS1_OAEP_PADDING).toString(fixture.UTF8); + assert.equal(decoded, fixture.PLAINTEXT); + + // Test with old-style padding. + encoded = rsa.publicEncrypt(plainBuf, ursaNative.RSA_PKCS1_PADDING); + decoded = priv.privateDecrypt(encoded, ursaNative.RSA_PKCS1_PADDING); + decoded = decoded.toString(fixture.UTF8); + assert.equal(decoded, fixture.PLAINTEXT); + }); + + it('fail_publicEncrypt', function() { + var rsa = new RsaWrap(); + + function f1() { + rsa.publicEncrypt(); + } + + assert.throws(f1, /Key not yet set\./); + + rsa = new RsaWrap(); + rsa.setPublicKeyPem(fixture.PUBLIC_KEY); + + function f2() { + rsa.publicEncrypt("x", ursaNative.RSA_PKCS1_OAEP_PADDING); + } + assert.throws(f2, /Expected a Buffer in args\[0]\./); + + function f3() { + rsa.publicEncrypt(new Buffer(2048), ursaNative.RSA_PKCS1_OAEP_PADDING); + } + assert.throws(f3, /too large/); + + function f4() { + rsa.publicEncrypt(new Buffer("x"), "str"); + } + assert.throws(f4, /Expected a 32-bit integer/); + }); + + it('privateEncrypt', function() { + var rsa = new RsaWrap(); + rsa.setPrivateKeyPem(fixture.PRIVATE_KEY); + + var plainBuf = new Buffer(fixture.PLAINTEXT, fixture.UTF8); + var encoded = rsa.privateEncrypt(plainBuf, ursaNative.RSA_PKCS1_PADDING).toString(fixture.HEX); + + assert.equal(encoded, fixture.PUBLIC_CIPHERTEXT_HEX); + }); + + it('fail_privateEncrypt', function() { + var rsa = new RsaWrap(); + + function f1() { + rsa.privateEncrypt(); + } + + assert.throws(f1, /Key not yet set\./); + + rsa = new RsaWrap(); + rsa.setPublicKeyPem(fixture.PUBLIC_KEY); + assert.throws(f1, /Expected a private key\./); + + rsa = new RsaWrap(); + rsa.setPrivateKeyPem(fixture.PRIVATE_KEY); + + function f2() { + rsa.privateEncrypt("x", ursaNative.RSA_PKCS1_PADDING); + } + assert.throws(f2, /Expected a Buffer in args\[0]\./); + + function f3() { + rsa.privateEncrypt(new Buffer(2048), ursaNative.RSA_PKCS1_PADDING); + } + assert.throws(f3, /too large/); + }); + + it('publicDecrypt', function() { + var rsa = new RsaWrap(); + rsa.setPublicKeyPem(fixture.PUBLIC_KEY); + var encoded = new Buffer(fixture.PUBLIC_CIPHERTEXT_HEX, fixture.HEX); + var decoded = rsa.publicDecrypt(encoded, ursaNative.RSA_PKCS1_PADDING).toString(fixture.UTF8); + assert.equal(decoded, fixture.PLAINTEXT); + + rsa = new RsaWrap(); + rsa.setPrivateKeyPem(fixture.PRIVATE_KEY); + encoded = new Buffer(fixture.PUBLIC_CIPHERTEXT_HEX, fixture.HEX); + decoded = rsa.publicDecrypt(encoded, ursaNative.RSA_PKCS1_PADDING).toString(fixture.UTF8); + assert.equal(decoded, fixture.PLAINTEXT); + }); + + it('fail_publicDecrypt', function() { + var rsa = new RsaWrap(); + + function f1() { + rsa.publicDecrypt(); + } + + assert.throws(f1, /Key not yet set\./); + rsa.setPublicKeyPem(fixture.PUBLIC_KEY); + + function f2() { + rsa.publicDecrypt("x", ursaNative.RSA_PKCS1_PADDING); + } + assert.throws(f2, /Expected a Buffer in args\[0]\./); + + function f3() { + rsa.publicDecrypt(new Buffer("x"), ursaNative.RSA_PKCS1_PADDING); + } + assert.throws(f3, /padding_check/); + }); + + it('generatePrivateKey', function() { + var rsa = new RsaWrap(); + rsa.generatePrivateKey(512, 65537); + + // Do a round trip check. + var plainBuf = new Buffer(fixture.PLAINTEXT, fixture.UTF8); + var encoded = rsa.publicEncrypt(plainBuf, ursaNative.RSA_PKCS1_OAEP_PADDING); + var decoded = rsa.privateDecrypt(encoded, ursaNative.RSA_PKCS1_OAEP_PADDING).toString(fixture.UTF8); + assert.equal(decoded, fixture.PLAINTEXT); + + // Extract the public key, and try using it for a round trip. + var pubKey = new RsaWrap(); + pubKey.setPublicKeyPem(rsa.getPublicKeyPem()); + encoded = pubKey.publicEncrypt(plainBuf, ursaNative.RSA_PKCS1_OAEP_PADDING); + decoded = rsa.privateDecrypt(encoded, ursaNative.RSA_PKCS1_OAEP_PADDING).toString(fixture.UTF8); + assert.equal(decoded, fixture.PLAINTEXT); + + // Similarly, try decoding with an extracted private key. + var privKey = new RsaWrap(); + privKey.setPrivateKeyPem(rsa.getPrivateKeyPem()); + decoded = privKey.privateDecrypt(encoded, ursaNative.RSA_PKCS1_OAEP_PADDING).toString(fixture.UTF8); + assert.equal(decoded, fixture.PLAINTEXT); + }); + + it('fail_generatePrivateKey', function() { + var rsa = new RsaWrap(); + + function f1() { + rsa.generatePrivateKey(); + } + assert.throws(f1, /Missing args\[0]\./); + + function f2() { + rsa.generatePrivateKey("x"); + } + assert.throws(f2, /Expected a 32-bit integer in args\[0]\./); + + function f3() { + rsa.generatePrivateKey(10); + } + assert.throws(f3, /Missing args\[1]\./); + + function f4() { + rsa.generatePrivateKey(20, "x"); + } + assert.throws(f4, /Expected a 32-bit integer in args\[1]\./); + + function f5() { + rsa.generatePrivateKey(512, 2); + } + assert.throws(f5, /Expected odd exponent\./); + + function f6() { + rsa.generatePrivateKey(512, 0); + } + assert.throws(f6, /Expected positive exponent\./); + + function f7() { + rsa.generatePrivateKey(511, 1); + } + assert.throws(f7, /Expected modulus bit count >= 512\./); + + // Use the original f1(), above, for this test. + rsa.setPublicKeyPem(fixture.PUBLIC_KEY); + assert.throws(f1, /Key already set\./); + }); + + it('sign', function() { + var rsa = new RsaWrap(); + rsa.setPrivateKeyPem(fixture.PRIVATE_KEY); + + var buf = new Buffer(fixture.FAKE_SHA256_TO_SIGN, fixture.HEX); + var sig = rsa.sign(textToNid(fixture.SHA256), buf); + + assert.equal(sig.toString(fixture.HEX), fixture.FAKE_SHA256_SIGNATURE); + + buf = new Buffer(fixture.PLAINTEXT_SHA256, fixture.HEX); + sig = rsa.sign(textToNid(fixture.SHA256), buf); + + assert.equal(sig.toString(fixture.HEX), fixture.PLAINTEXT_SHA256_SIGNATURE); + }); + + it('fail_sign', function() { + var rsa = new RsaWrap(); + + function f1() { + rsa.sign(); + } + + assert.throws(f1, /Key not yet set\./); + + rsa = new RsaWrap(); + rsa.setPublicKeyPem(fixture.PUBLIC_KEY); + assert.throws(f1, /Expected a private key\./); + + rsa = new RsaWrap(); + rsa.setPrivateKeyPem(fixture.PRIVATE_KEY); + + function f2() { + rsa.sign("x", "x"); + } + assert.throws(f2, /Expected a 32-bit integer in args\[0]\./); + + function f3() { + rsa.sign(1, "x"); + } + assert.throws(f3, /Expected a Buffer in args\[1]\./); + + function f4() { + rsa.sign(1, new Buffer(2048)); + } + assert.throws(f4, /too big/); + + function f5() { + rsa.sign(99999, new Buffer(16)); + } + assert.throws(f5, /unknown algorithm/); + }); + + it('verify', function() { + var rsa = new RsaWrap(); + rsa.setPublicKeyPem(fixture.PUBLIC_KEY); + + var hash = new Buffer(fixture.FAKE_SHA256_TO_SIGN, fixture.HEX); + var sig = new Buffer(fixture.FAKE_SHA256_SIGNATURE, fixture.HEX); + assert.equal(rsa.verify(textToNid(fixture.SHA256), hash, sig), true); + + // Private keys should be able to verify too. + hash = new Buffer(fixture.PLAINTEXT_SHA256, fixture.HEX); + sig = new Buffer(fixture.PLAINTEXT_SHA256_SIGNATURE, fixture.HEX); + assert.equal(rsa.verify(textToNid(fixture.SHA256), hash, sig), true); + + // Signature mismatch should return false (and not, e.g., throw). + hash = new Buffer(fixture.FAKE_SHA256_TO_SIGN, fixture.HEX); + sig = new Buffer(fixture.PLAINTEXT_SHA256_SIGNATURE, fixture.HEX); + assert.equal(rsa.verify(textToNid(fixture.SHA256), hash, sig), false); + }); + + it('fail_verify', function() { + var rsa = new RsaWrap(); + + function f1() { + rsa.verify(); + } + + assert.throws(f1, /Key not yet set\./); + + rsa = new RsaWrap(); + rsa.setPublicKeyPem(fixture.PUBLIC_KEY); + + function f2() { + rsa.verify("x", "x", "x"); + } + assert.throws(f2, /Expected a 32-bit integer in args\[0]\./); + + function f3() { + rsa.verify(1, "x", "x"); + } + assert.throws(f3, /Expected a Buffer in args\[1]\./); + + function f4() { + rsa.verify(1, new Buffer(16), "x"); + } + assert.throws(f4, /Expected a Buffer in args\[2]\./); + + function f5() { + var hash = new Buffer(10); + var sig = new Buffer(5); + hash.fill(0); + sig.fill(0); + rsa.verify(1, hash, sig); + } + assert.throws(f5, /wrong signature length/); + + function f6() { + var buf = new Buffer(256); + buf.fill(0); + rsa.verify(1, new Buffer(10), buf); + } + assert.throws(f6, /padding_check/); + + function f7() { + var hash = new Buffer(fixture.PLAINTEXT_SHA256, fixture.HEX); + var sig = new Buffer(fixture.PLAINTEXT_SHA256_SIGNATURE, fixture.HEX); + rsa.verify(textToNid(fixture.SHA1), hash, sig); + } + if (nodeVersion < 10) { + assert.throws(f7, /algorithm mismatch/); + } else { + assert.ifError(f7(), true); + } + + function f8() { + var hash = new Buffer(fixture.PLAINTEXT_SHA256, fixture.HEX); + var sig = new Buffer(fixture.PLAINTEXT_SHA256_SIGNATURE, fixture.HEX); + rsa.verify(1234567, hash, sig); + } + assert.throws(f8, nodeVersion < 10 ? /algorithm mismatch/ : /unknown algorithm type/); + }); + + it('textToNid', function() { + // I don't think you can count on the return values being anything + // other than integer values and that aliases should return equal + // values. + + function verifyInt(value) { + if (typeof value !== "number") { + throw new Exception("Not a number: " + value); + } + + if (value !== Math.floor(value)) { + throw new Exception("Not an integer: " + value); + } + } + + verifyInt(textToNid("aes-128-ecb")); + verifyInt(textToNid("md5")); + verifyInt(textToNid("rsa")); + verifyInt(textToNid("sha1")); + verifyInt(textToNid("sha256")); + verifyInt(textToNid("RSA-SHA256")); + verifyInt(textToNid("pkcs7")); + + assert.equal(textToNid("RSA-SHA256"), textToNid("sha256WithRSAEncryption")); + assert.equal(textToNid("AES-128-ECB"), textToNid("aes-128-ecb")); + }); + + it('fail_textToNid', function() { + function f1() { + textToNid(); + } + assert.throws(f1, /Missing args\[0\]/); + + function f2() { + textToNid(123); + } + assert.throws(f2, /Expected a string in args\[0\]/); + + function f3() { + textToNid("blort"); + } + assert.throws(f3, /asn1/); + }); + + it('PSSPadding', function() { + _test_PSSPadding(ursaNative.RSA_PKCS1_SALT_LEN_HLEN); + _test_PSSPadding(ursaNative.RSA_PKCS1_SALT_LEN_RECOVER); + + var rsa = new RsaWrap(); + rsa.createPublicKeyFromComponents( + new Buffer(fixture.PSS_MODULUS_HEX, fixture.HEX), + new Buffer(fixture.EXPONENT_HEX, fixture.HEX)); + + var tvhash = new Buffer(fixture.PSS_MHASH_HEX, fixture.HEX); + var tvem = new Buffer(fixture.PSS_EM_HEX, fixture.HEX); + + assert.equal(rsa.verifyPSSPadding( + textToNid(fixture.SHA1), tvhash, tvem, ursaNative.RSA_PKCS1_SALT_LEN_HLEN), true); + }); + + it('fail_PSSPadding', function() { + var rsa = new RsaWrap(); + + function f1() { + rsa.addPSSPadding(); + } + assert.throws(f1, /Key not yet set\./); + rsa.setPublicKeyPem(fixture.PUBLIC_KEY); + assert.throws(f1, /Not enough args\./); + + var nid = textToNid(fixture.SHA256); + var hash = new Buffer(fixture.FAKE_SHA256_TO_SIGN, fixture.HEX); + var slen = ursaNative.RSA_PKCS1_SALT_LEN_HLEN; + + function f2() { + rsa.addPSSPadding("x", hash, slen); + } + assert.throws(f2, /Expected a 32-bit integer in args\[0\]\./); + + function f3() { + rsa.addPSSPadding(nid, "x", slen); + } + assert.throws(f3, /Expected a Buffer in args\[1\]\./); + + function f4() { + rsa.addPSSPadding(nid, hash, "x"); + } + assert.throws(f4, /Expected a 32-bit integer in args\[2\]\./); + + function f5() { + rsa.addPSSPadding(nid, hash, 1000000); + } + assert.throws(f5, /data too large for key size/); + + function f6() { + rsa.addPSSPadding(nid, hash, -3); + } + assert.throws(f6, /salt length check failed/); + + var em = rsa.addPSSPadding(nid, hash, slen); + + function f7() { + rsa.verifyPSSPadding(); + } + assert.throws(f7, /Not enough args\./); + + function f8() { + rsa.verifyPSSPadding("x", hash, em, slen); + } + assert.throws(f8, /Expected a 32-bit integer in args\[0\]\./); + + function f9() { + rsa.verifyPSSPadding(nid, "x", em, slen); + } + assert.throws(f9, /Expected a Buffer in args\[1\]\./); + + function f10() { + rsa.verifyPSSPadding(nid, hash, "x", slen); + } + assert.throws(f10, /Expected a Buffer in args\[2\]\./); + + function f11() { + rsa.verifyPSSPadding(nid, hash, em, "x"); + } + assert.throws(f11, /Expected a 32-bit integer in args\[3\]\./); + + function f12() { + rsa.verifyPSSPadding(nid, hash, em, 1000000); + } + assert.throws(f12, /data too large/); + + function f13() { + rsa.verifyPSSPadding(nid, hash, em, -3); + } + assert.throws(f13, /salt length check failed/); + + em[em.length-1] ^= 2; + + function f14() { + rsa.verifyPSSPadding(nid, hash, em, slen); + } + assert.throws(f14, /last octet invalid/); + + em[em.length-1] ^= 2; + em[1] ^= 2; + assert.throws(f14, /salt length recovery failed/); + }); +}) + +function _test_PSSPadding(slen) +{ + var rsa = new RsaWrap(); + rsa.setPublicKeyPem(fixture.PUBLIC_KEY); + + var nid = textToNid(fixture.SHA256); + var hash = new Buffer(fixture.FAKE_SHA256_TO_SIGN, fixture.HEX); + var em = rsa.addPSSPadding(nid, hash, slen); + + assert.equal(rsa.verifyPSSPadding(nid, hash, em, slen), true); +} diff --git a/express-server/node_modules/ursa-optional/test/pss_tv.pub b/express-server/node_modules/ursa-optional/test/pss_tv.pub new file mode 100644 index 00000000..2a42a918 --- /dev/null +++ b/express-server/node_modules/ursa-optional/test/pss_tv.pub @@ -0,0 +1,6 @@ +-----BEGIN PUBLIC KEY----- +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCiukDuB+OyvS8CziJ/NqGVAkSG +5JwZy0G7vfu6mLIrDld8Lur/og2IOnbmXjlMadSzwFoej63aJ+2ypCvAAP6Ii5sy +wi0VrdDNdrPnk24ZlVsiDdF9TqkEsewQKy5N53USIqqZFRAkx8tBzF6iHQDutB98 +gAg00sbga847zn6ppQIDAQAB +-----END PUBLIC KEY----- diff --git a/express-server/node_modules/ursa-optional/test/test.js b/express-server/node_modules/ursa-optional/test/test.js new file mode 100644 index 00000000..52d028e3 --- /dev/null +++ b/express-server/node_modules/ursa-optional/test/test.js @@ -0,0 +1,608 @@ +// Copyright 2012 The Obvious Corporation. + +/* + * Tests of ursa + */ + +/* + * Modules used + */ + +"use strict"; + +var assert = require("assert"); + +var fixture = require("./fixture"); +var ursa = fixture.ursa; + +/** + * Asserts that two strings are equal, ignoring Windows newline differences + */ +function assertStringEqual(actual, expected, message) { + assert.equal(actual.replace(/\r\n/g, '\n'), expected.replace(/\r\n/g, '\n'), message); +} + +/* + * Helper functions + */ + +function test_getExponent(key) { + var buf = key.getExponent(); + assert.equal(buf.toString(fixture.HEX), fixture.EXPONENT_HEX); + + var result = key.getExponent(fixture.HEX); + assert.equal(result, fixture.EXPONENT_HEX); + + result = key.getExponent(fixture.BASE64); + assert.equal(result, buf.toString(fixture.BASE64)); + + result = key.getExponent(fixture.BINARY); + assert.equal(result, buf.toString(fixture.BINARY)); + + result = key.getExponent(fixture.UTF8); + assert.equal(result, buf.toString(fixture.UTF8)); +} + +function test_getModulus(key) { + var buf = key.getModulus(); + assert.equal(buf.toString(fixture.HEX), fixture.MODULUS_HEX); + + var result = key.getModulus(fixture.HEX); + assert.equal(result, fixture.MODULUS_HEX); + + result = key.getModulus(fixture.BASE64); + assert.equal(result, buf.toString(fixture.BASE64)); + + result = key.getModulus(fixture.BINARY); + assert.equal(result, buf.toString(fixture.BINARY)); + + result = key.getModulus(fixture.UTF8); + assert.equal(result, buf.toString(fixture.UTF8)); +} + +function test_toPublicPem(key) { + var keyString = fixture.PUBLIC_KEY.toString(fixture.UTF8); + var result = key.toPublicPem().toString(fixture.UTF8); + assertStringEqual(result, keyString); + + result = key.toPublicPem(fixture.UTF8); + assertStringEqual(result, keyString); +} + +function test_toPublicSsh(key) { + var keyString = fixture.SSH_PUBLIC_KEY.toString(fixture.BASE64); + var result = key.toPublicSsh().toString(fixture.BASE64); + assert.equal(result, keyString); + + result = key.toPublicSsh(fixture.BASE64); + assert.equal(result, keyString); +} + +function test_toPublicSshFingerprint(key) { + var result = key.toPublicSshFingerprint().toString(fixture.HEX); + assert.equal(result, fixture.SSH_PUBLIC_KEY_FINGERPRINT_HEX); + + result = key.toPublicSshFingerprint(fixture.HEX); + assert.equal(result, fixture.SSH_PUBLIC_KEY_FINGERPRINT_HEX); +} + +function test_encrypt(key) { + // The sanest way to test this is to do a round trip. + var privKey = ursa.createPrivateKey(fixture.PRIVATE_KEY) + var encoded = key.encrypt(new Buffer(fixture.PLAINTEXT, fixture.UTF8)); + var decoded = privKey.decrypt(encoded, undefined, fixture.UTF8); + assert.equal(decoded, fixture.PLAINTEXT); + + encoded = key.encrypt(fixture.PLAINTEXT, fixture.UTF8, fixture.BASE64); + decoded = privKey.decrypt(encoded, fixture.BASE64, fixture.UTF8); + assert.equal(decoded, fixture.PLAINTEXT); + + encoded = key.encrypt(fixture.PLAINTEXT, undefined, fixture.HEX); + decoded = privKey.decrypt(encoded, fixture.HEX, fixture.UTF8); + assert.equal(decoded, fixture.PLAINTEXT); +} + +function test_publicDecrypt(key) { + var encoded = new Buffer(fixture.PUBLIC_CIPHERTEXT_HEX, fixture.HEX); + var decoded = key.publicDecrypt(encoded).toString(fixture.UTF8); + assert.equal(decoded, fixture.PLAINTEXT); + + decoded = key.publicDecrypt(fixture.PUBLIC_CIPHERTEXT_HEX, fixture.HEX, + fixture.UTF8); + assert.equal(decoded, fixture.PLAINTEXT); + + decoded = key.publicDecrypt(fixture.PUBLIC_CIPHERTEXT_NP_HEX, fixture.HEX, + fixture.UTF8, ursa.RSA_NO_PADDING); + assert.equal(decoded, fixture.PLAINTEXT_PADDED); +} + +function test_verify(key) { + assert.equal(key.verify(fixture.SHA256, fixture.PLAINTEXT_SHA256, + fixture.PLAINTEXT_SHA256_SIGNATURE, + fixture.HEX), true); + + var hash = new Buffer(fixture.PLAINTEXT_SHA256, fixture.HEX); + var sig = new Buffer(fixture.PLAINTEXT_SHA256_SIGNATURE, fixture.HEX); + assert.equal(key.verify(fixture.SHA256, hash, sig), true); +} + +function test_hashAndVerify(key) { + assert.equal(key.hashAndVerify(fixture.SHA256, + new Buffer(fixture.PLAINTEXT, fixture.UTF8), + fixture.PLAINTEXT_SHA256_SIGNATURE, + fixture.HEX), + true); + + var key2 = ursa.createPublicKeyFromComponents( + new Buffer(fixture.PSS_MODULUS_HEX, fixture.HEX), + new Buffer(fixture.EXPONENT_HEX, fixture.HEX)); + + assert.equal(key2.hashAndVerify(fixture.SHA1, + fixture.PSS_M_HEX, + fixture.PSS_S_HEX, + fixture.HEX, + true, + ursa.RSA_PKCS1_SALT_LEN_HLEN), + true); + + assert.equal(key2.hashAndVerify(fixture.SHA1, + fixture.PSS_M_HEX, + fixture.PSS_S_HEX, + fixture.HEX, + true), + true); +} + +function testPublicKeyMethods(key) { + test_getExponent(key); + test_getModulus(key); + test_toPublicPem(key); + test_toPublicSsh(key); + test_toPublicSshFingerprint(key); + test_encrypt(key); + test_publicDecrypt(key); + test_verify(key); + test_hashAndVerify(key); +} + +function test_toPrivatePem(key) { + var keyString = fixture.PRIVATE_KEY.toString(fixture.UTF8); + var result = key.toPrivatePem().toString(fixture.UTF8); + assertStringEqual(result, keyString); + + result = key.toPrivatePem(fixture.UTF8); + assertStringEqual(result, keyString); +} + +function test_toEncryptedPrivatePem(key) { + var password = fixture.PASSWORD.toString(fixture.UTF8); + var cipher = fixture.DES_EDE3_CBC; + + var keyString = fixture.PASS_PRIVATE_KEY.toString(fixture.UTF8); + var pem = key.toEncryptedPrivatePem(password, cipher).toString(fixture.UTF8); + + var plainTextKey = ursa.createPrivateKey(pem, password); + assertStringEqual(plainTextKey.toPrivatePem().toString(), fixture.PRIVATE_KEY.toString()); + + + pem = key.toEncryptedPrivatePem(password, cipher, fixture.UTF8).toString(fixture.UTF8); + + plainTextKey = ursa.createPrivateKey(pem, password); + assertStringEqual(plainTextKey.toPrivatePem().toString(), fixture.PRIVATE_KEY.toString()); +} + +function test_decrypt(key) { + var encoded = new Buffer(fixture.PRIVATE_CIPHERTEXT_HEX, fixture.HEX); + var decoded = key.decrypt(encoded).toString(fixture.UTF8); + assert.equal(decoded, fixture.PLAINTEXT); + + decoded = key.decrypt(fixture.PRIVATE_CIPHERTEXT_HEX, fixture.HEX, + fixture.UTF8); + assert.equal(decoded, fixture.PLAINTEXT); +} + +function test_privateEncrypt(key) { + var encoded = key.privateEncrypt( + new Buffer(fixture.PLAINTEXT, fixture.UTF8)).toString(fixture.HEX); + assert.equal(encoded, fixture.PUBLIC_CIPHERTEXT_HEX); + + encoded = key.privateEncrypt(fixture.PLAINTEXT, fixture.UTF8, fixture.HEX); + assert.equal(encoded, fixture.PUBLIC_CIPHERTEXT_HEX); + + encoded = key.privateEncrypt(fixture.PLAINTEXT, undefined, fixture.HEX); + assert.equal(encoded, fixture.PUBLIC_CIPHERTEXT_HEX); + + encoded = key.privateEncrypt(fixture.PLAINTEXT_PADDED, fixture.UTF8, fixture.HEX, ursa.RSA_NO_PADDING); + assert.equal(encoded, fixture.PUBLIC_CIPHERTEXT_NP_HEX); +} + +function test_sign(key) { + var sig = key.sign(fixture.SHA256, + fixture.PLAINTEXT_SHA256, fixture.HEX, + fixture.BASE64); + sig = new Buffer(sig, fixture.BASE64); + assert.equal(sig.toString(fixture.HEX), fixture.PLAINTEXT_SHA256_SIGNATURE); + + var buf = new Buffer(fixture.PLAINTEXT_SHA256, fixture.HEX); + sig = key.sign(fixture.SHA256, buf, undefined, fixture.HEX); + assert.equal(sig, fixture.PLAINTEXT_SHA256_SIGNATURE); +} + +function test_hashAndSign(key) { + var sig = key.hashAndSign(fixture.SHA256, fixture.PLAINTEXT, + fixture.UTF8, fixture.HEX); + assert.equal(sig, fixture.PLAINTEXT_SHA256_SIGNATURE); + + // PSS uses random salt so can't have a fixture + + var sig = key.hashAndSign(fixture.SHA256, fixture.PLAINTEXT, + fixture.UTF8, fixture.HEX, + true, ursa.RSA_PKCS1_SALT_LEN_MAX); + + assert.equal(key.hashAndVerify( + fixture.SHA256, + new Buffer(fixture.PLAINTEXT).toString(fixture.HEX), + sig, + fixture.HEX, + true, + ursa.RSA_PKCS1_SALT_LEN_MAX), + true); +} + +function testPrivateKeyMethods(key) { + test_toPrivatePem(key); + test_toEncryptedPrivatePem(key); + test_decrypt(key); + test_privateEncrypt(key); + test_hashAndSign(key); + test_sign(key); +} + +describe('main', function() { + it('Basics', function() { + ursa.createPublicKey(fixture.PUBLIC_KEY); + ursa.createPrivateKey(fixture.PRIVATE_KEY); + ursa.createPrivateKey(fixture.PASS_PRIVATE_KEY, fixture.PASSWORD); + ursa.generatePrivateKey(512); + + ursa.createPublicKey(fixture.PUBLIC_KEY.toString(fixture.UTF8)); + ursa.createPrivateKey(fixture.PRIVATE_KEY.toString(fixture.BASE64), + undefined, fixture.BASE64); + }); + + it('Types', function() { + var pub = ursa.createPublicKey(fixture.PUBLIC_KEY); + var priv = ursa.createPrivateKey(fixture.PRIVATE_KEY); + var msg; + + msg = "Problem with isKey()"; + assert.equal(ursa.isKey(pub), true, msg); + assert.equal(ursa.isKey(priv), true, msg); + assert.equal(ursa.isKey(undefined), false, msg); + assert.equal(ursa.isKey("x"), false, msg); + + msg = "Problem with isPublicKey()"; + assert.equal(ursa.isPublicKey(pub), true, msg); + assert.equal(ursa.isPublicKey(priv), false, msg); + assert.equal(ursa.isPublicKey(undefined), false, msg); + assert.equal(ursa.isPublicKey("x"), false, msg); + + msg = "Problem with isPrivateKey()"; + assert.equal(ursa.isPrivateKey(pub), false, msg); + assert.equal(ursa.isPrivateKey(priv), true, msg); + assert.equal(ursa.isPrivateKey(undefined), false, msg); + assert.equal(ursa.isPrivateKey("x"), false, msg); + + assert.doesNotThrow(function () { ursa.assertKey(pub); }); + assert.doesNotThrow(function () { ursa.assertKey(priv); }); + assert.throws(function () { ursa.assertKey(undefined); }); + assert.throws(function () { ursa.assertKey("x"); }); + + assert.doesNotThrow(function () { ursa.assertPublicKey(pub); }); + assert.throws(function () { ursa.assertPublicKey(priv); }); + assert.throws(function () { ursa.assertPublicKey(undefined); }); + assert.throws(function () { ursa.assertPublicKey("x"); }); + + assert.throws(function () { ursa.assertPrivateKey(pub); }); + assert.doesNotThrow(function () { ursa.assertPrivateKey(priv); }); + assert.throws(function () { ursa.assertPrivateKey(undefined); }); + assert.throws(function () { ursa.assertPrivateKey("x"); }); + }); + + it('createKey', function() { + var priv = ursa.createKey(fixture.PRIVATE_KEY); + assert(ursa.isPrivateKey(priv), true); + + var pub = ursa.createKey(fixture.PUBLIC_KEY); + assert(ursa.isPublicKey(pub), true); + + function f1() { + ursa.createKey("yo there"); + } + assert.throws(f1, /Not a key\./); + }); + + it('createPrivateKeyFromComponents', function() { + var privFromComponents = ursa.createPrivateKeyFromComponents( + fixture.PRIVATE_KEY_COMPONENTS.modulus, + fixture.PRIVATE_KEY_COMPONENTS.exponent, + fixture.PRIVATE_KEY_COMPONENTS.p, + fixture.PRIVATE_KEY_COMPONENTS.q, + fixture.PRIVATE_KEY_COMPONENTS.dp, + fixture.PRIVATE_KEY_COMPONENTS.dq, + fixture.PRIVATE_KEY_COMPONENTS.inverseQ, + fixture.PRIVATE_KEY_COMPONENTS.d); + + assert(ursa.isPrivateKey(privFromComponents), true); + + var privFromPem = ursa.createPrivateKey(fixture.PRIVATE_KEY_3); + + assert.equal(privFromComponents.toPrivatePem('utf8'), privFromPem.toPrivatePem('utf8')); + }); + + it('createPublicKeyFromComponents', function() { + var pubFromComponents = ursa.createPublicKeyFromComponents( + new Buffer(fixture.PSS_MODULUS_HEX, fixture.HEX), + new Buffer(fixture.EXPONENT_HEX, fixture.HEX)); + + assert(ursa.isPublicKey(pubFromComponents), true); + + var pubFromPem = ursa.createPublicKey(fixture.PSS_PUBLIC_KEY); + + assert.equal(pubFromComponents.toPublicPem('utf8'), + pubFromPem.toPublicPem('utf8')); + }); + + it('fail_createPublicKey', function() { + // This is mostly tested at the native level. This just tests the + // extra failures added at the high level. + function f1() { + ursa.createPublicKey(fixture.PRIVATE_KEY); + } + assert.throws(f1, /Not a public key\./); + }); + + it('fail_createPrivateKey', function() { + // This is mostly tested at the native level. This just tests the + // extra failures added at the high level. + function f1() { + ursa.createPrivateKey(fixture.PUBLIC_KEY); + } + assert.throws(f1, /Not a private key\./); + }); + + it('coerceKey', function() { + var priv = ursa.coerceKey(fixture.PRIVATE_KEY); + assert(ursa.isPrivateKey(priv), true); + + priv = ursa.coerceKey(fixture.PRIVATE_KEY.toString()); + assert(ursa.isPrivateKey(priv), true); + + var pub = ursa.coerceKey(fixture.PUBLIC_KEY); + assert(ursa.isPublicKey(pub), true); + + pub = ursa.coerceKey(fixture.PUBLIC_KEY.toString()); + assert(ursa.isPublicKey(pub), true); + + assert.equal(ursa.coerceKey(priv), priv); + assert.equal(ursa.coerceKey(pub), pub); + }); + + it('coercePrivateKey', function() { + var priv = ursa.coercePrivateKey(fixture.PRIVATE_KEY); + assert(ursa.isPrivateKey(priv), true); + + priv = ursa.coercePrivateKey(fixture.PRIVATE_KEY.toString()); + assert(ursa.isPrivateKey(priv), true); + + assert.equal(ursa.coercePrivateKey(priv), priv); + }); + + it('coercePublicKey', function() { + var pub = ursa.coercePublicKey(fixture.PUBLIC_KEY); + assert(ursa.isPublicKey(pub), true); + + pub = ursa.coercePublicKey(fixture.PUBLIC_KEY.toString()); + assert(ursa.isPublicKey(pub), true); + + assert.equal(ursa.coercePublicKey(pub), pub); + }); + + it('fail_coerceKey', function() { + function f1() { + ursa.coerceKey("foo"); + } + assert.throws(f1, /Not a key/); + + function f2() { + ursa.coerceKey(new Buffer(200)); + } + assert.throws(f2, /Not a key/); + + function f3() { + ursa.coerceKey([]); + } + assert.throws(f3, /Not a key/); + }); + + it('fail_coercePrivateKey', function() { + function f1() { + ursa.coercePrivateKey("foo"); + } + assert.throws(f1, /Not a private key/); + + function f2() { + ursa.coercePrivateKey(new Buffer(200)); + } + assert.throws(f2, /Not a private key/); + + function f3() { + ursa.coercePrivateKey([]); + } + assert.throws(f3, /Not a private key/); + + function f4() { + ursa.coercePrivateKey(fixture.PUBLIC_KEY); + } + assert.throws(f4, /Not a private key/); + + function f5() { + ursa.coercePrivateKey(fixture.PUBLIC_KEY.toString()); + } + assert.throws(f5, /Not a private key/); + }); + + it('fail_coercePublicKey', function() { + function f1() { + ursa.coercePublicKey("foo"); + } + assert.throws(f1, /Not a public key/); + + function f2() { + ursa.coercePublicKey(new Buffer(200)); + } + assert.throws(f2, /Not a public key/); + + function f3() { + ursa.coercePublicKey([]); + } + assert.throws(f3, /Not a public key/); + + function f4() { + ursa.coercePublicKey(fixture.PRIVATE_KEY); + } + assert.throws(f4, /Not a public key/); + + function f5() { + ursa.coercePublicKey(fixture.PRIVATE_KEY.toString()); + } + assert.throws(f5, /Not a public key/); + }); + + it('PublicKey', function() { + var key = ursa.createPublicKey(fixture.PUBLIC_KEY); + testPublicKeyMethods(key); + }); + + it('PrivateKey', function() { + var key = ursa.createPrivateKey(fixture.PRIVATE_KEY); + testPublicKeyMethods(key); + testPrivateKeyMethods(key); + }); + + it('GeneratedKey', function() { + // Just do a round trip. If that works, then it's safe to believe + // the native tests (which are more comprehensive). + var key = ursa.generatePrivateKey(); + var encoded = key.encrypt(fixture.PLAINTEXT, fixture.UTF8); + var decoded = key.decrypt(encoded, undefined, fixture.UTF8); + assert.equal(decoded, fixture.PLAINTEXT); + }); + + it('sshFingerprint', function() { + var key = fixture.SSH_PUBLIC_KEY; + var finger = ursa.sshFingerprint(fixture.SSH_PUBLIC_KEY); + assert.equal(finger.toString(fixture.HEX), + fixture.SSH_PUBLIC_KEY_FINGERPRINT_HEX); + + finger = ursa.sshFingerprint(fixture.SSH_PUBLIC_KEY, undefined, + fixture.HEX); + assert.equal(finger, fixture.SSH_PUBLIC_KEY_FINGERPRINT_HEX); + + finger = ursa.sshFingerprint( + fixture.SSH_PUBLIC_KEY.toString(fixture.BASE64), + fixture.BASE64, fixture.HEX); + assert.equal(finger, fixture.SSH_PUBLIC_KEY_FINGERPRINT_HEX); + }); + + it('equalKeys', function() { + var pub = ursa.createPublicKey(fixture.PUBLIC_KEY); + var priv = ursa.createPrivateKey(fixture.PRIVATE_KEY); + var samePub = ursa.createPublicKey(fixture.PUBLIC_KEY); + var samePriv = ursa.createPrivateKey(fixture.PRIVATE_KEY); + var diffPub = ursa.createPublicKey(fixture.PUBLIC_KEY_2); + var diffPriv = ursa.createPrivateKey(fixture.PRIVATE_KEY_2); + + assert.equal(ursa.equalKeys("1", "2"), false); + assert.equal(ursa.equalKeys(123, 123), false); + assert.equal(ursa.equalKeys(pub, null), false); + assert.equal(ursa.equalKeys(true, pub), false); + + assert.equal(ursa.equalKeys(pub, pub), true); + assert.equal(ursa.equalKeys(priv, priv), true); + assert.equal(ursa.equalKeys(pub, priv), false); + assert.equal(ursa.equalKeys(priv, pub), false); + + assert.equal(ursa.equalKeys(pub, samePub), true); + assert.equal(ursa.equalKeys(priv, samePriv), true); + + assert.equal(ursa.equalKeys(pub, diffPub), false); + assert.equal(ursa.equalKeys(priv, diffPriv), false); + }); + + it('matchingPublicKeys', function() { + var pub = ursa.createPublicKey(fixture.PUBLIC_KEY); + var priv = ursa.createPrivateKey(fixture.PRIVATE_KEY); + var samePub = ursa.createPublicKey(fixture.PUBLIC_KEY); + var samePriv = ursa.createPrivateKey(fixture.PRIVATE_KEY); + var diffPub = ursa.createPublicKey(fixture.PUBLIC_KEY_2); + var diffPriv = ursa.createPrivateKey(fixture.PRIVATE_KEY_2); + + assert.equal(ursa.matchingPublicKeys("1", "2"), false); + assert.equal(ursa.matchingPublicKeys(123, 123), false); + assert.equal(ursa.matchingPublicKeys(pub, null), false); + assert.equal(ursa.matchingPublicKeys(true, pub), false); + + assert.equal(ursa.matchingPublicKeys(pub, pub), true); + assert.equal(ursa.matchingPublicKeys(priv, priv), true); + assert.equal(ursa.matchingPublicKeys(pub, priv), true); + assert.equal(ursa.matchingPublicKeys(priv, pub), true); + + assert.equal(ursa.matchingPublicKeys(pub, samePub), true); + assert.equal(ursa.matchingPublicKeys(priv, samePriv), true); + assert.equal(ursa.matchingPublicKeys(pub, samePriv), true); + assert.equal(ursa.matchingPublicKeys(priv, samePub), true); + + assert.equal(ursa.matchingPublicKeys(pub, diffPub), false); + assert.equal(ursa.matchingPublicKeys(pub, diffPriv), false); + assert.equal(ursa.matchingPublicKeys(priv, diffPriv), false); + assert.equal(ursa.matchingPublicKeys(priv, diffPub), false); + }); + + it('Signer', function() { + var key = ursa.createPrivateKey(fixture.PRIVATE_KEY); + var signer = ursa.createSigner(fixture.SHA256); + + var ret = signer.update(fixture.PLAINTEXT, fixture.UTF8); + assert.equal(ret === signer, true); + + var sig = signer.sign(key, fixture.HEX); + + assert.equal(sig, fixture.PLAINTEXT_SHA256_SIGNATURE); + }); + + it('Verifier', function() { + var key = ursa.createPublicKey(fixture.PUBLIC_KEY); + var verifier = ursa.createVerifier(fixture.SHA256); + + var ret = verifier.update(fixture.PLAINTEXT, fixture.UTF8); + assert.equal(ret === verifier, true); + + + assert.equal(verifier.verify(key, fixture.PLAINTEXT_SHA256_SIGNATURE, + fixture.HEX), + true); + + var verifier = ursa.createVerifier(fixture.SHA256); + verifier.update(new Buffer(fixture.PLAINTEXT, fixture.UTF8)); + var sigBuf = new Buffer(fixture.PLAINTEXT_SHA256_SIGNATURE, fixture.HEX); + assert.equal(verifier.verify(key, sigBuf), true); + }); + + it('openSshPublicKey', function() { + var sshKey = ursa.openSshPublicKey(fixture.SSH_PUBLIC_KEY), + pubKey = ursa.createPublicKey(fixture.PUBLIC_KEY); + + assert.equal(ursa.equalKeys(sshKey, pubKey), true); + }); +}) diff --git a/express-server/node_modules/ursa-optional/test/zorch.pem b/express-server/node_modules/ursa-optional/test/zorch.pem new file mode 100644 index 00000000..21a58cf0 --- /dev/null +++ b/express-server/node_modules/ursa-optional/test/zorch.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAtZPKWwG02rHQAZP95ckEo/rY7nAOJO+TRT5Kf7Ym4xJGBMCc +5Ach5j4o1OFzKWaHgtfGM01Le3fdGx4VwxLcSlUI9ixvlhhKEqkRpGr8vphCDx0v +g+jXseQ2axrR6uHrdYA+8ASnfiuxILDXCRLwmPlliFA4D0qoWenOmqeNT7+98opZ +eN0BQxiOE/MXluSVpdVK/IQo5ggFDMBrHmq2+5L2I7JNkZOxADcilecrSrg1bt3F +ppKWGt49tpcCldOFx50iXE7ca1y4fOtBx0rm4JPzmFIYB1hu3mIT/xd3p2MY5dMr +Q9kYbeRcxcal1xXreLyWf2KslrPwwxZFR9QVoQIDAQABAoIBAGhaJ1FmCaolxoUh +qCkG/cO/xixB+d8AUILa6bW72V1mgxb4GzJxZuoLjyvI5YZFhluL5jxVj6vFlyye +faM+k5ukgyH3J6n7C5bt01XKprZiipRlEYmdp1h071FeeIWkkM1WhtUp15iLQ6Cm +AO8WE2/W5KMSdyVSoq4J0NLQuEW705nRBw0KvKOu/16MI3ASIYAhDh2N+celiq0B +QEFdMNIY4mQwRmoW8+nTVh3szVd6GXMH0etcQlDz7dLwXYm4qSw+dQusFjYZ6s4U +HKjIxFsCy32B8XoLKi2gKY0u4SE56H9Qcp05y1fZe20lfenf3Der0ucrX0THj1/Z +HLSTJgECgYEA6qlVbK0gm/iX8p62U/t3e1NtHyv3UlmmFPuHS4Z/cX4hErym0FJk +ln/Ggo2cSlyw83TjQFPRGvCDbULa/pKJow0PyGk0+LHELk5bguGtq0EMpd2ZmUKs +QIPcWXzbzismuH3x8zcNvErCEWvU7aDW8NznZes/a4aIjUR8DdG/l6UCgYEAxha2 +/EBp5YTubNIIVSROUMpzYmrJJSMdvCz7eu0yfREQFzAbgyhdOkBx7jdAzAVAINOw +iVNP2h/DcOwGgcTun7RpBQ4QToDviNKQwp2Vh/DTYpuGzYgDJzmb+UawXQhXR9/F +eWzYkb2HFZVQ6Quhd0uFE71B4NFD1FPqEDfERU0CgYBBPt/fnauJcm9dKD/tzeeE +xMd8eU8E+KQzBVSy7SyWM8miWg3PsnkBV3msZw9jpa4VoxRkmGl1ohYI1SPq0Hew +fDs9L/NoipTPgz3ygCk3ipinrZu9f0pBjehAgXTkOB9GAM67Hz2UcvzOtzq275eT +1PgJ4IT7sqZZEQelGAK7eQKBgDunK4Pbggh0d7idp5S8UjlSPl0s+1YLtTCt+y2R +sNqpAMd63U4qIakhLy4lxYWrLxyzoz43sJxnZFvlODBsNdAybE3xZke93GS/xIhX +HGjLxVy0qWvLwedWGfp/pyzdDiu+36Epfi6lfMCrLqp/rihWvcSsAeLKIjsW6i3o +HVshAoGActqcGaI+rt5A1FFwzNbZYiu8QLjtMV+Je8oryP58HZTfDf31vkIi3MdR +G4jDp9POKxkn+AIfX6GOt2skC+mJGACbjPXCcuSaIYS6LyUmdZ22N+063yiiex2M +irL6oqJcmS8k8DD34fhNPC+Z8KMkcqp0xNm9ikmJLNmEY5eeaiI= +-----END RSA PRIVATE KEY----- diff --git a/express-server/node_modules/ursa-optional/test/zorch.pub b/express-server/node_modules/ursa-optional/test/zorch.pub new file mode 100644 index 00000000..c3ca9585 --- /dev/null +++ b/express-server/node_modules/ursa-optional/test/zorch.pub @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtZPKWwG02rHQAZP95ckE +o/rY7nAOJO+TRT5Kf7Ym4xJGBMCc5Ach5j4o1OFzKWaHgtfGM01Le3fdGx4VwxLc +SlUI9ixvlhhKEqkRpGr8vphCDx0vg+jXseQ2axrR6uHrdYA+8ASnfiuxILDXCRLw +mPlliFA4D0qoWenOmqeNT7+98opZeN0BQxiOE/MXluSVpdVK/IQo5ggFDMBrHmq2 ++5L2I7JNkZOxADcilecrSrg1bt3FppKWGt49tpcCldOFx50iXE7ca1y4fOtBx0rm +4JPzmFIYB1hu3mIT/xd3p2MY5dMrQ9kYbeRcxcal1xXreLyWf2KslrPwwxZFR9QV +oQIDAQAB +-----END PUBLIC KEY----- diff --git a/express-server/node_modules/utils-merge/.npmignore b/express-server/node_modules/utils-merge/.npmignore new file mode 100644 index 00000000..3e538441 --- /dev/null +++ b/express-server/node_modules/utils-merge/.npmignore @@ -0,0 +1,9 @@ +CONTRIBUTING.md +Makefile +docs/ +examples/ +reports/ +test/ + +.jshintrc +.travis.yml diff --git a/express-server/node_modules/ws/LICENSE b/express-server/node_modules/ws/LICENSE new file mode 100644 index 00000000..a145cd1d --- /dev/null +++ b/express-server/node_modules/ws/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2011 Einar Otto Stangvik + +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/express-server/node_modules/ws/README.md b/express-server/node_modules/ws/README.md new file mode 100644 index 00000000..3fd9a8cc --- /dev/null +++ b/express-server/node_modules/ws/README.md @@ -0,0 +1,417 @@ +# ws: a Node.js WebSocket library + +[![Version npm](https://img.shields.io/npm/v/ws.svg)](https://www.npmjs.com/package/ws) +[![Linux Build](https://img.shields.io/travis/websockets/ws/master.svg)](https://travis-ci.org/websockets/ws) +[![Windows Build](https://ci.appveyor.com/api/projects/status/github/websockets/ws?branch=master&svg=true)](https://ci.appveyor.com/project/lpinca/ws) +[![Coverage Status](https://img.shields.io/coveralls/websockets/ws/master.svg)](https://coveralls.io/r/websockets/ws?branch=master) + +ws is a simple to use, blazing fast, and thoroughly tested WebSocket client +and server implementation. + +Passes the quite extensive Autobahn test suite: [server][server-report], +[client][client-report]. + +**Note**: This module does not work in the browser. The client in the docs is a +reference to a back end with the role of a client in the WebSocket +communication. Browser clients must use the native +[`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) object. +To make the same code work seamlessly on Node.js and the browser, you can use +one of the many wrappers available on npm, like +[isomorphic-ws](https://github.com/heineiuo/isomorphic-ws). + +## Table of Contents + +* [Protocol support](#protocol-support) +* [Installing](#installing) + + [Opt-in for performance and spec compliance](#opt-in-for-performance-and-spec-compliance) +* [API docs](#api-docs) +* [WebSocket compression](#websocket-compression) +* [Usage examples](#usage-examples) + + [Sending and receiving text data](#sending-and-receiving-text-data) + + [Sending binary data](#sending-binary-data) + + [Simple server](#simple-server) + + [External HTTP/S server](#external-https-server) + + [Multiple servers sharing a single HTTP/S server](#multiple-servers-sharing-a-single-https-server) + + [Server broadcast](#server-broadcast) + + [echo.websocket.org demo](#echowebsocketorg-demo) + + [Other examples](#other-examples) +* [Error handling best practices](#error-handling-best-practices) +* [FAQ](#faq) + + [How to get the IP address of the client?](#how-to-get-the-ip-address-of-the-client) + + [How to detect and close broken connections?](#how-to-detect-and-close-broken-connections) + + [How to connect via a proxy?](#how-to-connect-via-a-proxy) +* [Changelog](#changelog) +* [License](#license) + +## Protocol support + +* **HyBi drafts 07-12** (Use the option `protocolVersion: 8`) +* **HyBi drafts 13-17** (Current default, alternatively option `protocolVersion: 13`) + +## Installing + +``` +npm install --save ws +``` + +### Opt-in for performance and spec compliance + +There are 2 optional modules that can be installed along side with the ws +module. These modules are binary addons which improve certain operations. +Prebuilt binaries are available for the most popular platforms so you don't +necessarily need to have a C++ compiler installed on your machine. + +- `npm install --save-optional bufferutil`: Allows to efficiently perform + operations such as masking and unmasking the data payload of the WebSocket + frames. +- `npm install --save-optional utf-8-validate`: Allows to efficiently check + if a message contains valid UTF-8 as required by the spec. + +## API docs + +See [`/doc/ws.md`](./doc/ws.md) for Node.js-like docs for the ws classes. + +## WebSocket compression + +ws supports the [permessage-deflate extension][permessage-deflate] which +enables the client and server to negotiate a compression algorithm and its +parameters, and then selectively apply it to the data payloads of each +WebSocket message. + +The extension is disabled by default on the server and enabled by default on +the client. It adds a significant overhead in terms of performance and memory +consumption so we suggest to enable it only if it is really needed. + +Note that Node.js has a variety of issues with high-performance compression, +where increased concurrency, especially on Linux, can lead to +[catastrophic memory fragmentation][node-zlib-bug] and slow performance. +If you intend to use permessage-deflate in production, it is worthwhile to set +up a test representative of your workload and ensure Node.js/zlib will handle +it with acceptable performance and memory usage. + +Tuning of permessage-deflate can be done via the options defined below. You can +also use `zlibDeflateOptions` and `zlibInflateOptions`, which is passed directly +into the creation of [raw deflate/inflate streams][node-zlib-deflaterawdocs]. + +See [the docs][ws-server-options] for more options. + +```js +const WebSocket = require('ws'); + +const wss = new WebSocket.Server({ + port: 8080, + perMessageDeflate: { + zlibDeflateOptions: { // See zlib defaults. + chunkSize: 1024, + memLevel: 7, + level: 3, + }, + zlibInflateOptions: { + chunkSize: 10 * 1024 + }, + // Other options settable: + clientNoContextTakeover: true, // Defaults to negotiated value. + serverNoContextTakeover: true, // Defaults to negotiated value. + clientMaxWindowBits: 10, // Defaults to negotiated value. + serverMaxWindowBits: 10, // Defaults to negotiated value. + // Below options specified as default values. + concurrencyLimit: 10, // Limits zlib concurrency for perf. + threshold: 1024, // Size (in bytes) below which messages + // should not be compressed. + } +}); +``` + +The client will only use the extension if it is supported and enabled on the +server. To always disable the extension on the client set the +`perMessageDeflate` option to `false`. + +```js +const WebSocket = require('ws'); + +const ws = new WebSocket('ws://www.host.com/path', { + perMessageDeflate: false +}); +``` + +## Usage examples + +### Sending and receiving text data + +```js +const WebSocket = require('ws'); + +const ws = new WebSocket('ws://www.host.com/path'); + +ws.on('open', function open() { + ws.send('something'); +}); + +ws.on('message', function incoming(data) { + console.log(data); +}); +``` + +### Sending binary data + +```js +const WebSocket = require('ws'); + +const ws = new WebSocket('ws://www.host.com/path'); + +ws.on('open', function open() { + const array = new Float32Array(5); + + for (var i = 0; i < array.length; ++i) { + array[i] = i / 2; + } + + ws.send(array); +}); +``` + +### Simple server + +```js +const WebSocket = require('ws'); + +const wss = new WebSocket.Server({ port: 8080 }); + +wss.on('connection', function connection(ws) { + ws.on('message', function incoming(message) { + console.log('received: %s', message); + }); + + ws.send('something'); +}); +``` + +### External HTTP/S server + +```js +const fs = require('fs'); +const https = require('https'); +const WebSocket = require('ws'); + +const server = new https.createServer({ + cert: fs.readFileSync('/path/to/cert.pem'), + key: fs.readFileSync('/path/to/key.pem') +}); +const wss = new WebSocket.Server({ server }); + +wss.on('connection', function connection(ws) { + ws.on('message', function incoming(message) { + console.log('received: %s', message); + }); + + ws.send('something'); +}); + +server.listen(8080); +``` + +### Multiple servers sharing a single HTTP/S server + +```js +const http = require('http'); +const WebSocket = require('ws'); + +const server = http.createServer(); +const wss1 = new WebSocket.Server({ noServer: true }); +const wss2 = new WebSocket.Server({ noServer: true }); + +wss1.on('connection', function connection(ws) { + // ... +}); + +wss2.on('connection', function connection(ws) { + // ... +}); + +server.on('upgrade', function upgrade(request, socket, head) { + const pathname = url.parse(request.url).pathname; + + if (pathname === '/foo') { + wss1.handleUpgrade(request, socket, head, function done(ws) { + wss1.emit('connection', ws, request); + }); + } else if (pathname === '/bar') { + wss2.handleUpgrade(request, socket, head, function done(ws) { + wss2.emit('connection', ws, request); + }); + } else { + socket.destroy(); + } +}); + +server.listen(8080); +``` + +### Server broadcast + +```js +const WebSocket = require('ws'); + +const wss = new WebSocket.Server({ port: 8080 }); + +// Broadcast to all. +wss.broadcast = function broadcast(data) { + wss.clients.forEach(function each(client) { + if (client.readyState === WebSocket.OPEN) { + client.send(data); + } + }); +}; + +wss.on('connection', function connection(ws) { + ws.on('message', function incoming(data) { + // Broadcast to everyone else. + wss.clients.forEach(function each(client) { + if (client !== ws && client.readyState === WebSocket.OPEN) { + client.send(data); + } + }); + }); +}); +``` + +### echo.websocket.org demo + +```js +const WebSocket = require('ws'); + +const ws = new WebSocket('wss://echo.websocket.org/', { + origin: 'https://websocket.org' +}); + +ws.on('open', function open() { + console.log('connected'); + ws.send(Date.now()); +}); + +ws.on('close', function close() { + console.log('disconnected'); +}); + +ws.on('message', function incoming(data) { + console.log(`Roundtrip time: ${Date.now() - data} ms`); + + setTimeout(function timeout() { + ws.send(Date.now()); + }, 500); +}); +``` + +### Other examples + +For a full example with a browser client communicating with a ws server, see the +examples folder. + +Otherwise, see the test cases. + +## Error handling best practices + +```js +// If the WebSocket is closed before the following send is attempted +ws.send('something'); + +// Errors (both immediate and async write errors) can be detected in an optional +// callback. The callback is also the only way of being notified that data has +// actually been sent. +ws.send('something', function ack(error) { + // If error is not defined, the send has been completed, otherwise the error + // object will indicate what failed. +}); + +// Immediate errors can also be handled with `try...catch`, but **note** that +// since sends are inherently asynchronous, socket write failures will *not* be +// captured when this technique is used. +try { ws.send('something'); } +catch (e) { /* handle error */ } +``` + +## FAQ + +### How to get the IP address of the client? + +The remote IP address can be obtained from the raw socket. + +```js +const WebSocket = require('ws'); + +const wss = new WebSocket.Server({ port: 8080 }); + +wss.on('connection', function connection(ws, req) { + const ip = req.connection.remoteAddress; +}); +``` + +When the server runs behind a proxy like NGINX, the de-facto standard is to use +the `X-Forwarded-For` header. + +```js +wss.on('connection', function connection(ws, req) { + const ip = req.headers['x-forwarded-for'].split(/\s*,\s*/)[0]; +}); +``` + +### How to detect and close broken connections? + +Sometimes the link between the server and the client can be interrupted in a +way that keeps both the server and the client unaware of the broken state of the +connection (e.g. when pulling the cord). + +In these cases ping messages can be used as a means to verify that the remote +endpoint is still responsive. + +```js +const WebSocket = require('ws'); + +const wss = new WebSocket.Server({ port: 8080 }); + +function noop() {} + +function heartbeat() { + this.isAlive = true; +} + +wss.on('connection', function connection(ws) { + ws.isAlive = true; + ws.on('pong', heartbeat); +}); + +const interval = setInterval(function ping() { + wss.clients.forEach(function each(ws) { + if (ws.isAlive === false) return ws.terminate(); + + ws.isAlive = false; + ws.ping(noop); + }); +}, 30000); +``` + +Pong messages are automatically sent in response to ping messages as required +by the spec. + +### How to connect via a proxy? + +Use a custom `http.Agent` implementation like [https-proxy-agent][] or +[socks-proxy-agent][]. + +## Changelog + +We're using the GitHub [releases][changelog] for changelog entries. + +## License + +[MIT](LICENSE) + +[https-proxy-agent]: https://github.com/TooTallNate/node-https-proxy-agent +[socks-proxy-agent]: https://github.com/TooTallNate/node-socks-proxy-agent +[client-report]: http://websockets.github.io/ws/autobahn/clients/ +[server-report]: http://websockets.github.io/ws/autobahn/servers/ +[permessage-deflate]: https://tools.ietf.org/html/rfc7692 +[changelog]: https://github.com/websockets/ws/releases +[node-zlib-bug]: https://github.com/nodejs/node/issues/8871 +[node-zlib-deflaterawdocs]: https://nodejs.org/api/zlib.html#zlib_zlib_createdeflateraw_options +[ws-server-options]: https://github.com/websockets/ws/blob/master/doc/ws.md#new-websocketserveroptions-callback diff --git a/express-server/node_modules/ws/index.js b/express-server/node_modules/ws/index.js new file mode 100644 index 00000000..b8d6be1c --- /dev/null +++ b/express-server/node_modules/ws/index.js @@ -0,0 +1,9 @@ +'use strict'; + +const WebSocket = require('./lib/websocket'); + +WebSocket.Server = require('./lib/websocket-server'); +WebSocket.Receiver = require('./lib/receiver'); +WebSocket.Sender = require('./lib/sender'); + +module.exports = WebSocket; diff --git a/express-server/node_modules/ws/lib/buffer-util.js b/express-server/node_modules/ws/lib/buffer-util.js new file mode 100644 index 00000000..6974dd6a --- /dev/null +++ b/express-server/node_modules/ws/lib/buffer-util.js @@ -0,0 +1,72 @@ +'use strict'; + +/** + * Merges an array of buffers into a new buffer. + * + * @param {Buffer[]} list The array of buffers to concat + * @param {Number} totalLength The total length of buffers in the list + * @return {Buffer} The resulting buffer + * @public + */ +function concat (list, totalLength) { + const target = Buffer.allocUnsafe(totalLength); + var offset = 0; + + for (var i = 0; i < list.length; i++) { + const buf = list[i]; + buf.copy(target, offset); + offset += buf.length; + } + + return target; +} + +/** + * Masks a buffer using the given mask. + * + * @param {Buffer} source The buffer to mask + * @param {Buffer} mask The mask to use + * @param {Buffer} output The buffer where to store the result + * @param {Number} offset The offset at which to start writing + * @param {Number} length The number of bytes to mask. + * @public + */ +function _mask (source, mask, output, offset, length) { + for (var i = 0; i < length; i++) { + output[offset + i] = source[i] ^ mask[i & 3]; + } +} + +/** + * Unmasks a buffer using the given mask. + * + * @param {Buffer} buffer The buffer to unmask + * @param {Buffer} mask The mask to use + * @public + */ +function _unmask (buffer, mask) { + // Required until https://github.com/nodejs/node/issues/9006 is resolved. + const length = buffer.length; + for (var i = 0; i < length; i++) { + buffer[i] ^= mask[i & 3]; + } +} + +try { + const bufferUtil = require('bufferutil'); + const bu = bufferUtil.BufferUtil || bufferUtil; + + module.exports = { + mask (source, mask, output, offset, length) { + if (length < 48) _mask(source, mask, output, offset, length); + else bu.mask(source, mask, output, offset, length); + }, + unmask (buffer, mask) { + if (buffer.length < 32) _unmask(buffer, mask); + else bu.unmask(buffer, mask); + }, + concat + }; +} catch (e) /* istanbul ignore next */ { + module.exports = { concat, mask: _mask, unmask: _unmask }; +} diff --git a/express-server/node_modules/ws/lib/constants.js b/express-server/node_modules/ws/lib/constants.js new file mode 100644 index 00000000..4082981f --- /dev/null +++ b/express-server/node_modules/ws/lib/constants.js @@ -0,0 +1,10 @@ +'use strict'; + +module.exports = { + BINARY_TYPES: ['nodebuffer', 'arraybuffer', 'fragments'], + GUID: '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', + kStatusCode: Symbol('status-code'), + kWebSocket: Symbol('websocket'), + EMPTY_BUFFER: Buffer.alloc(0), + NOOP: () => {} +}; diff --git a/express-server/node_modules/ws/lib/event-target.js b/express-server/node_modules/ws/lib/event-target.js new file mode 100644 index 00000000..574e9080 --- /dev/null +++ b/express-server/node_modules/ws/lib/event-target.js @@ -0,0 +1,170 @@ +'use strict'; + +/** + * Class representing an event. + * + * @private + */ +class Event { + /** + * Create a new `Event`. + * + * @param {String} type The name of the event + * @param {Object} target A reference to the target to which the event was dispatched + */ + constructor (type, target) { + this.target = target; + this.type = type; + } +} + +/** + * Class representing a message event. + * + * @extends Event + * @private + */ +class MessageEvent extends Event { + /** + * Create a new `MessageEvent`. + * + * @param {(String|Buffer|ArrayBuffer|Buffer[])} data The received data + * @param {WebSocket} target A reference to the target to which the event was dispatched + */ + constructor (data, target) { + super('message', target); + + this.data = data; + } +} + +/** + * Class representing a close event. + * + * @extends Event + * @private + */ +class CloseEvent extends Event { + /** + * Create a new `CloseEvent`. + * + * @param {Number} code The status code explaining why the connection is being closed + * @param {String} reason A human-readable string explaining why the connection is closing + * @param {WebSocket} target A reference to the target to which the event was dispatched + */ + constructor (code, reason, target) { + super('close', target); + + this.wasClean = target._closeFrameReceived && target._closeFrameSent; + this.reason = reason; + this.code = code; + } +} + +/** + * Class representing an open event. + * + * @extends Event + * @private + */ +class OpenEvent extends Event { + /** + * Create a new `OpenEvent`. + * + * @param {WebSocket} target A reference to the target to which the event was dispatched + */ + constructor (target) { + super('open', target); + } +} + +/** + * Class representing an error event. + * + * @extends Event + * @private + */ +class ErrorEvent extends Event { + /** + * Create a new `ErrorEvent`. + * + * @param {Object} error The error that generated this event + * @param {WebSocket} target A reference to the target to which the event was dispatched + */ + constructor (error, target) { + super('error', target); + + this.message = error.message; + this.error = error; + } +} + +/** + * This provides methods for emulating the `EventTarget` interface. It's not + * meant to be used directly. + * + * @mixin + */ +const EventTarget = { + /** + * Register an event listener. + * + * @param {String} method A string representing the event type to listen for + * @param {Function} listener The listener to add + * @public + */ + addEventListener (method, listener) { + if (typeof listener !== 'function') return; + + function onMessage (data) { + listener.call(this, new MessageEvent(data, this)); + } + + function onClose (code, message) { + listener.call(this, new CloseEvent(code, message, this)); + } + + function onError (error) { + listener.call(this, new ErrorEvent(error, this)); + } + + function onOpen () { + listener.call(this, new OpenEvent(this)); + } + + if (method === 'message') { + onMessage._listener = listener; + this.on(method, onMessage); + } else if (method === 'close') { + onClose._listener = listener; + this.on(method, onClose); + } else if (method === 'error') { + onError._listener = listener; + this.on(method, onError); + } else if (method === 'open') { + onOpen._listener = listener; + this.on(method, onOpen); + } else { + this.on(method, listener); + } + }, + + /** + * Remove an event listener. + * + * @param {String} method A string representing the event type to remove + * @param {Function} listener The listener to remove + * @public + */ + removeEventListener (method, listener) { + const listeners = this.listeners(method); + + for (var i = 0; i < listeners.length; i++) { + if (listeners[i] === listener || listeners[i]._listener === listener) { + this.removeListener(method, listeners[i]); + } + } + } +}; + +module.exports = EventTarget; diff --git a/express-server/node_modules/ws/lib/extension.js b/express-server/node_modules/ws/lib/extension.js new file mode 100644 index 00000000..3f48d751 --- /dev/null +++ b/express-server/node_modules/ws/lib/extension.js @@ -0,0 +1,211 @@ +'use strict'; + +// +// Allowed token characters: +// +// '!', '#', '$', '%', '&', ''', '*', '+', '-', +// '.', 0-9, A-Z, '^', '_', '`', a-z, '|', '~' +// +// tokenChars[32] === 0 // ' ' +// tokenChars[33] === 1 // '!' +// tokenChars[34] === 0 // '"' +// ... +// +const tokenChars = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 15 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31 + 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32 - 47 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48 - 63 + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80 - 95 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0 // 112 - 127 +]; + +/** + * Adds an offer to the map of extension offers or a parameter to the map of + * parameters. + * + * @param {Object} dest The map of extension offers or parameters + * @param {String} name The extension or parameter name + * @param {(Object|Boolean|String)} elem The extension parameters or the + * parameter value + * @private + */ +function push (dest, name, elem) { + if (Object.prototype.hasOwnProperty.call(dest, name)) dest[name].push(elem); + else dest[name] = [elem]; +} + +/** + * Parses the `Sec-WebSocket-Extensions` header into an object. + * + * @param {String} header The field value of the header + * @return {Object} The parsed object + * @public + */ +function parse (header) { + const offers = {}; + + if (header === undefined || header === '') return offers; + + var params = {}; + var mustUnescape = false; + var isEscaping = false; + var inQuotes = false; + var extensionName; + var paramName; + var start = -1; + var end = -1; + + for (var i = 0; i < header.length; i++) { + const code = header.charCodeAt(i); + + if (extensionName === undefined) { + if (end === -1 && tokenChars[code] === 1) { + if (start === -1) start = i; + } else if (code === 0x20/* ' ' */|| code === 0x09/* '\t' */) { + if (end === -1 && start !== -1) end = i; + } else if (code === 0x3b/* ';' */ || code === 0x2c/* ',' */) { + if (start === -1) { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + + if (end === -1) end = i; + const name = header.slice(start, end); + if (code === 0x2c) { + push(offers, name, params); + params = {}; + } else { + extensionName = name; + } + + start = end = -1; + } else { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + } else if (paramName === undefined) { + if (end === -1 && tokenChars[code] === 1) { + if (start === -1) start = i; + } else if (code === 0x20 || code === 0x09) { + if (end === -1 && start !== -1) end = i; + } else if (code === 0x3b || code === 0x2c) { + if (start === -1) { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + + if (end === -1) end = i; + push(params, header.slice(start, end), true); + if (code === 0x2c) { + push(offers, extensionName, params); + params = {}; + extensionName = undefined; + } + + start = end = -1; + } else if (code === 0x3d/* '=' */&& start !== -1 && end === -1) { + paramName = header.slice(start, i); + start = end = -1; + } else { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + } else { + // + // The value of a quoted-string after unescaping must conform to the + // token ABNF, so only token characters are valid. + // Ref: https://tools.ietf.org/html/rfc6455#section-9.1 + // + if (isEscaping) { + if (tokenChars[code] !== 1) { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + if (start === -1) start = i; + else if (!mustUnescape) mustUnescape = true; + isEscaping = false; + } else if (inQuotes) { + if (tokenChars[code] === 1) { + if (start === -1) start = i; + } else if (code === 0x22/* '"' */ && start !== -1) { + inQuotes = false; + end = i; + } else if (code === 0x5c/* '\' */) { + isEscaping = true; + } else { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + } else if (code === 0x22 && header.charCodeAt(i - 1) === 0x3d) { + inQuotes = true; + } else if (end === -1 && tokenChars[code] === 1) { + if (start === -1) start = i; + } else if (start !== -1 && (code === 0x20 || code === 0x09)) { + if (end === -1) end = i; + } else if (code === 0x3b || code === 0x2c) { + if (start === -1) { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + + if (end === -1) end = i; + var value = header.slice(start, end); + if (mustUnescape) { + value = value.replace(/\\/g, ''); + mustUnescape = false; + } + push(params, paramName, value); + if (code === 0x2c) { + push(offers, extensionName, params); + params = {}; + extensionName = undefined; + } + + paramName = undefined; + start = end = -1; + } else { + throw new SyntaxError(`Unexpected character at index ${i}`); + } + } + } + + if (start === -1 || inQuotes) { + throw new SyntaxError('Unexpected end of input'); + } + + if (end === -1) end = i; + const token = header.slice(start, end); + if (extensionName === undefined) { + push(offers, token, {}); + } else { + if (paramName === undefined) { + push(params, token, true); + } else if (mustUnescape) { + push(params, paramName, token.replace(/\\/g, '')); + } else { + push(params, paramName, token); + } + push(offers, extensionName, params); + } + + return offers; +} + +/** + * Builds the `Sec-WebSocket-Extensions` header field value. + * + * @param {Object} extensions The map of extensions and parameters to format + * @return {String} A string representing the given object + * @public + */ +function format (extensions) { + return Object.keys(extensions).map((extension) => { + var configurations = extensions[extension]; + if (!Array.isArray(configurations)) configurations = [configurations]; + return configurations.map((params) => { + return [extension].concat(Object.keys(params).map((k) => { + var values = params[k]; + if (!Array.isArray(values)) values = [values]; + return values.map((v) => v === true ? k : `${k}=${v}`).join('; '); + })).join('; '); + }).join(', '); + }).join(', '); +} + +module.exports = { format, parse }; diff --git a/express-server/node_modules/ws/lib/permessage-deflate.js b/express-server/node_modules/ws/lib/permessage-deflate.js new file mode 100644 index 00000000..0d54f035 --- /dev/null +++ b/express-server/node_modules/ws/lib/permessage-deflate.js @@ -0,0 +1,516 @@ +'use strict'; + +const Limiter = require('async-limiter'); +const zlib = require('zlib'); + +const bufferUtil = require('./buffer-util'); +const constants = require('./constants'); + +const TRAILER = Buffer.from([0x00, 0x00, 0xff, 0xff]); +const EMPTY_BLOCK = Buffer.from([0x00]); + +const kPerMessageDeflate = Symbol('permessage-deflate'); +const kWriteInProgress = Symbol('write-in-progress'); +const kPendingClose = Symbol('pending-close'); +const kTotalLength = Symbol('total-length'); +const kCallback = Symbol('callback'); +const kBuffers = Symbol('buffers'); +const kError = Symbol('error'); + +// +// We limit zlib concurrency, which prevents severe memory fragmentation +// as documented in https://github.com/nodejs/node/issues/8871#issuecomment-250915913 +// and https://github.com/websockets/ws/issues/1202 +// +// Intentionally global; it's the global thread pool that's an issue. +// +let zlibLimiter; + +/** + * permessage-deflate implementation. + */ +class PerMessageDeflate { + /** + * Creates a PerMessageDeflate instance. + * + * @param {Object} options Configuration options + * @param {Boolean} options.serverNoContextTakeover Request/accept disabling + * of server context takeover + * @param {Boolean} options.clientNoContextTakeover Advertise/acknowledge + * disabling of client context takeover + * @param {(Boolean|Number)} options.serverMaxWindowBits Request/confirm the + * use of a custom server window size + * @param {(Boolean|Number)} options.clientMaxWindowBits Advertise support + * for, or request, a custom client window size + * @param {Object} options.zlibDeflateOptions Options to pass to zlib on deflate + * @param {Object} options.zlibInflateOptions Options to pass to zlib on inflate + * @param {Number} options.threshold Size (in bytes) below which messages + * should not be compressed + * @param {Number} options.concurrencyLimit The number of concurrent calls to + * zlib + * @param {Boolean} isServer Create the instance in either server or client + * mode + * @param {Number} maxPayload The maximum allowed message length + */ + constructor (options, isServer, maxPayload) { + this._maxPayload = maxPayload | 0; + this._options = options || {}; + this._threshold = this._options.threshold !== undefined + ? this._options.threshold + : 1024; + this._isServer = !!isServer; + this._deflate = null; + this._inflate = null; + + this.params = null; + + if (!zlibLimiter) { + const concurrency = this._options.concurrencyLimit !== undefined + ? this._options.concurrencyLimit + : 10; + zlibLimiter = new Limiter({ concurrency }); + } + } + + /** + * @type {String} + */ + static get extensionName () { + return 'permessage-deflate'; + } + + /** + * Create an extension negotiation offer. + * + * @return {Object} Extension parameters + * @public + */ + offer () { + const params = {}; + + if (this._options.serverNoContextTakeover) { + params.server_no_context_takeover = true; + } + if (this._options.clientNoContextTakeover) { + params.client_no_context_takeover = true; + } + if (this._options.serverMaxWindowBits) { + params.server_max_window_bits = this._options.serverMaxWindowBits; + } + if (this._options.clientMaxWindowBits) { + params.client_max_window_bits = this._options.clientMaxWindowBits; + } else if (this._options.clientMaxWindowBits == null) { + params.client_max_window_bits = true; + } + + return params; + } + + /** + * Accept an extension negotiation offer/response. + * + * @param {Array} configurations The extension negotiation offers/reponse + * @return {Object} Accepted configuration + * @public + */ + accept (configurations) { + configurations = this.normalizeParams(configurations); + + this.params = this._isServer + ? this.acceptAsServer(configurations) + : this.acceptAsClient(configurations); + + return this.params; + } + + /** + * Releases all resources used by the extension. + * + * @public + */ + cleanup () { + if (this._inflate) { + if (this._inflate[kWriteInProgress]) { + this._inflate[kPendingClose] = true; + } else { + this._inflate.close(); + this._inflate = null; + } + } + if (this._deflate) { + if (this._deflate[kWriteInProgress]) { + this._deflate[kPendingClose] = true; + } else { + this._deflate.close(); + this._deflate = null; + } + } + } + + /** + * Accept an extension negotiation offer. + * + * @param {Array} offers The extension negotiation offers + * @return {Object} Accepted configuration + * @private + */ + acceptAsServer (offers) { + const opts = this._options; + const accepted = offers.find((params) => { + if ( + (opts.serverNoContextTakeover === false && + params.server_no_context_takeover) || + (params.server_max_window_bits && + (opts.serverMaxWindowBits === false || + (typeof opts.serverMaxWindowBits === 'number' && + opts.serverMaxWindowBits > params.server_max_window_bits))) || + (typeof opts.clientMaxWindowBits === 'number' && + !params.client_max_window_bits) + ) { + return false; + } + + return true; + }); + + if (!accepted) { + throw new Error('None of the extension offers can be accepted'); + } + + if (opts.serverNoContextTakeover) { + accepted.server_no_context_takeover = true; + } + if (opts.clientNoContextTakeover) { + accepted.client_no_context_takeover = true; + } + if (typeof opts.serverMaxWindowBits === 'number') { + accepted.server_max_window_bits = opts.serverMaxWindowBits; + } + if (typeof opts.clientMaxWindowBits === 'number') { + accepted.client_max_window_bits = opts.clientMaxWindowBits; + } else if ( + accepted.client_max_window_bits === true || + opts.clientMaxWindowBits === false + ) { + delete accepted.client_max_window_bits; + } + + return accepted; + } + + /** + * Accept the extension negotiation response. + * + * @param {Array} response The extension negotiation response + * @return {Object} Accepted configuration + * @private + */ + acceptAsClient (response) { + const params = response[0]; + + if ( + this._options.clientNoContextTakeover === false && + params.client_no_context_takeover + ) { + throw new Error('Unexpected parameter "client_no_context_takeover"'); + } + + if (!params.client_max_window_bits) { + if (typeof this._options.clientMaxWindowBits === 'number') { + params.client_max_window_bits = this._options.clientMaxWindowBits; + } + } else if ( + this._options.clientMaxWindowBits === false || + (typeof this._options.clientMaxWindowBits === 'number' && + params.client_max_window_bits > this._options.clientMaxWindowBits) + ) { + throw new Error( + 'Unexpected or invalid parameter "client_max_window_bits"' + ); + } + + return params; + } + + /** + * Normalize parameters. + * + * @param {Array} configurations The extension negotiation offers/reponse + * @return {Array} The offers/response with normalized parameters + * @private + */ + normalizeParams (configurations) { + configurations.forEach((params) => { + Object.keys(params).forEach((key) => { + var value = params[key]; + + if (value.length > 1) { + throw new Error(`Parameter "${key}" must have only a single value`); + } + + value = value[0]; + + if (key === 'client_max_window_bits') { + if (value !== true) { + const num = +value; + if (!Number.isInteger(num) || num < 8 || num > 15) { + throw new TypeError( + `Invalid value for parameter "${key}": ${value}` + ); + } + value = num; + } else if (!this._isServer) { + throw new TypeError( + `Invalid value for parameter "${key}": ${value}` + ); + } + } else if (key === 'server_max_window_bits') { + const num = +value; + if (!Number.isInteger(num) || num < 8 || num > 15) { + throw new TypeError( + `Invalid value for parameter "${key}": ${value}` + ); + } + value = num; + } else if ( + key === 'client_no_context_takeover' || + key === 'server_no_context_takeover' + ) { + if (value !== true) { + throw new TypeError( + `Invalid value for parameter "${key}": ${value}` + ); + } + } else { + throw new Error(`Unknown parameter "${key}"`); + } + + params[key] = value; + }); + }); + + return configurations; + } + + /** + * Decompress data. Concurrency limited by async-limiter. + * + * @param {Buffer} data Compressed data + * @param {Boolean} fin Specifies whether or not this is the last fragment + * @param {Function} callback Callback + * @public + */ + decompress (data, fin, callback) { + zlibLimiter.push((done) => { + this._decompress(data, fin, (err, result) => { + done(); + callback(err, result); + }); + }); + } + + /** + * Compress data. Concurrency limited by async-limiter. + * + * @param {Buffer} data Data to compress + * @param {Boolean} fin Specifies whether or not this is the last fragment + * @param {Function} callback Callback + * @public + */ + compress (data, fin, callback) { + zlibLimiter.push((done) => { + this._compress(data, fin, (err, result) => { + done(); + callback(err, result); + }); + }); + } + + /** + * Decompress data. + * + * @param {Buffer} data Compressed data + * @param {Boolean} fin Specifies whether or not this is the last fragment + * @param {Function} callback Callback + * @private + */ + _decompress (data, fin, callback) { + const endpoint = this._isServer ? 'client' : 'server'; + + if (!this._inflate) { + const key = `${endpoint}_max_window_bits`; + const windowBits = typeof this.params[key] !== 'number' + ? zlib.Z_DEFAULT_WINDOWBITS + : this.params[key]; + + this._inflate = zlib.createInflateRaw( + Object.assign({}, this._options.zlibInflateOptions, { windowBits }) + ); + this._inflate[kPerMessageDeflate] = this; + this._inflate[kTotalLength] = 0; + this._inflate[kBuffers] = []; + this._inflate.on('error', inflateOnError); + this._inflate.on('data', inflateOnData); + } + + this._inflate[kCallback] = callback; + this._inflate[kWriteInProgress] = true; + + this._inflate.write(data); + if (fin) this._inflate.write(TRAILER); + + this._inflate.flush(() => { + const err = this._inflate[kError]; + + if (err) { + this._inflate.close(); + this._inflate = null; + callback(err); + return; + } + + const data = bufferUtil.concat( + this._inflate[kBuffers], + this._inflate[kTotalLength] + ); + + if ( + (fin && this.params[`${endpoint}_no_context_takeover`]) || + this._inflate[kPendingClose] + ) { + this._inflate.close(); + this._inflate = null; + } else { + this._inflate[kWriteInProgress] = false; + this._inflate[kTotalLength] = 0; + this._inflate[kBuffers] = []; + } + + callback(null, data); + }); + } + + /** + * Compress data. + * + * @param {Buffer} data Data to compress + * @param {Boolean} fin Specifies whether or not this is the last fragment + * @param {Function} callback Callback + * @private + */ + _compress (data, fin, callback) { + if (!data || data.length === 0) { + process.nextTick(callback, null, EMPTY_BLOCK); + return; + } + + const endpoint = this._isServer ? 'server' : 'client'; + + if (!this._deflate) { + const key = `${endpoint}_max_window_bits`; + const windowBits = typeof this.params[key] !== 'number' + ? zlib.Z_DEFAULT_WINDOWBITS + : this.params[key]; + + this._deflate = zlib.createDeflateRaw( + Object.assign( + // TODO deprecate memLevel/level and recommend zlibDeflateOptions instead + { + memLevel: this._options.memLevel, + level: this._options.level + }, + this._options.zlibDeflateOptions, + { windowBits } + ) + ); + + this._deflate[kTotalLength] = 0; + this._deflate[kBuffers] = []; + + // + // `zlib.DeflateRaw` emits an `'error'` event only when an attempt to use + // it is made after it has already been closed. This cannot happen here, + // so we only add a listener for the `'data'` event. + // + this._deflate.on('data', deflateOnData); + } + + this._deflate[kWriteInProgress] = true; + + this._deflate.write(data); + this._deflate.flush(zlib.Z_SYNC_FLUSH, () => { + var data = bufferUtil.concat( + this._deflate[kBuffers], + this._deflate[kTotalLength] + ); + + if (fin) data = data.slice(0, data.length - 4); + + if ( + (fin && this.params[`${endpoint}_no_context_takeover`]) || + this._deflate[kPendingClose] + ) { + this._deflate.close(); + this._deflate = null; + } else { + this._deflate[kWriteInProgress] = false; + this._deflate[kTotalLength] = 0; + this._deflate[kBuffers] = []; + } + + callback(null, data); + }); + } +} + +module.exports = PerMessageDeflate; + +/** + * The listener of the `zlib.DeflateRaw` stream `'data'` event. + * + * @param {Buffer} chunk A chunk of data + * @private + */ +function deflateOnData (chunk) { + this[kBuffers].push(chunk); + this[kTotalLength] += chunk.length; +} + +/** + * The listener of the `zlib.InflateRaw` stream `'data'` event. + * + * @param {Buffer} chunk A chunk of data + * @private + */ +function inflateOnData (chunk) { + this[kTotalLength] += chunk.length; + + if ( + this[kPerMessageDeflate]._maxPayload < 1 || + this[kTotalLength] <= this[kPerMessageDeflate]._maxPayload + ) { + this[kBuffers].push(chunk); + return; + } + + this[kError] = new RangeError('Max payload size exceeded'); + this[kError][constants.kStatusCode] = 1009; + this.removeListener('data', inflateOnData); + this.reset(); +} + +/** + * The listener of the `zlib.InflateRaw` stream `'error'` event. + * + * @param {Error} err The emitted error + * @private + */ +function inflateOnError (err) { + // + // There is no need to call `Zlib#close()` as the handle is automatically + // closed when an error is emitted. + // + this[kPerMessageDeflate]._inflate = null; + err[constants.kStatusCode] = 1007; + this[kCallback](err); +} diff --git a/express-server/node_modules/ws/lib/receiver.js b/express-server/node_modules/ws/lib/receiver.js new file mode 100644 index 00000000..81dc0bf8 --- /dev/null +++ b/express-server/node_modules/ws/lib/receiver.js @@ -0,0 +1,513 @@ +'use strict'; + +const stream = require('stream'); + +const PerMessageDeflate = require('./permessage-deflate'); +const bufferUtil = require('./buffer-util'); +const validation = require('./validation'); +const constants = require('./constants'); + +const GET_INFO = 0; +const GET_PAYLOAD_LENGTH_16 = 1; +const GET_PAYLOAD_LENGTH_64 = 2; +const GET_MASK = 3; +const GET_DATA = 4; +const INFLATING = 5; + +/** + * HyBi Receiver implementation. + * + * @extends stream.Writable + */ +class Receiver extends stream.Writable { + /** + * Creates a Receiver instance. + * + * @param {String} binaryType The type for binary data + * @param {Object} extensions An object containing the negotiated extensions + * @param {Number} maxPayload The maximum allowed message length + */ + constructor (binaryType, extensions, maxPayload) { + super(); + + this._binaryType = binaryType || constants.BINARY_TYPES[0]; + this[constants.kWebSocket] = undefined; + this._extensions = extensions || {}; + this._maxPayload = maxPayload | 0; + + this._bufferedBytes = 0; + this._buffers = []; + + this._compressed = false; + this._payloadLength = 0; + this._mask = undefined; + this._fragmented = 0; + this._masked = false; + this._fin = false; + this._opcode = 0; + + this._totalPayloadLength = 0; + this._messageLength = 0; + this._fragments = []; + + this._state = GET_INFO; + this._loop = false; + } + + /** + * Implements `Writable.prototype._write()`. + * + * @param {Buffer} chunk The chunk of data to write + * @param {String} encoding The character encoding of `chunk` + * @param {Function} cb Callback + */ + _write (chunk, encoding, cb) { + if (this._opcode === 0x08) return cb(); + + this._bufferedBytes += chunk.length; + this._buffers.push(chunk); + this.startLoop(cb); + } + + /** + * Consumes `n` bytes from the buffered data. + * + * @param {Number} n The number of bytes to consume + * @return {Buffer} The consumed bytes + * @private + */ + consume (n) { + this._bufferedBytes -= n; + + if (n === this._buffers[0].length) return this._buffers.shift(); + + if (n < this._buffers[0].length) { + const buf = this._buffers[0]; + this._buffers[0] = buf.slice(n); + return buf.slice(0, n); + } + + const dst = Buffer.allocUnsafe(n); + + do { + const buf = this._buffers[0]; + + if (n >= buf.length) { + this._buffers.shift().copy(dst, dst.length - n); + } else { + buf.copy(dst, dst.length - n, 0, n); + this._buffers[0] = buf.slice(n); + } + + n -= buf.length; + } while (n > 0); + + return dst; + } + + /** + * Starts the parsing loop. + * + * @param {Function} cb Callback + * @private + */ + startLoop (cb) { + var err; + this._loop = true; + + do { + switch (this._state) { + case GET_INFO: + err = this.getInfo(); + break; + case GET_PAYLOAD_LENGTH_16: + err = this.getPayloadLength16(); + break; + case GET_PAYLOAD_LENGTH_64: + err = this.getPayloadLength64(); + break; + case GET_MASK: + this.getMask(); + break; + case GET_DATA: + err = this.getData(cb); + break; + default: // `INFLATING` + this._loop = false; + return; + } + } while (this._loop); + + cb(err); + } + + /** + * Reads the first two bytes of a frame. + * + * @return {(RangeError|undefined)} A possible error + * @private + */ + getInfo () { + if (this._bufferedBytes < 2) { + this._loop = false; + return; + } + + const buf = this.consume(2); + + if ((buf[0] & 0x30) !== 0x00) { + this._loop = false; + return error(RangeError, 'RSV2 and RSV3 must be clear', true, 1002); + } + + const compressed = (buf[0] & 0x40) === 0x40; + + if (compressed && !this._extensions[PerMessageDeflate.extensionName]) { + this._loop = false; + return error(RangeError, 'RSV1 must be clear', true, 1002); + } + + this._fin = (buf[0] & 0x80) === 0x80; + this._opcode = buf[0] & 0x0f; + this._payloadLength = buf[1] & 0x7f; + + if (this._opcode === 0x00) { + if (compressed) { + this._loop = false; + return error(RangeError, 'RSV1 must be clear', true, 1002); + } + + if (!this._fragmented) { + this._loop = false; + return error(RangeError, 'invalid opcode 0', true, 1002); + } + + this._opcode = this._fragmented; + } else if (this._opcode === 0x01 || this._opcode === 0x02) { + if (this._fragmented) { + this._loop = false; + return error(RangeError, `invalid opcode ${this._opcode}`, true, 1002); + } + + this._compressed = compressed; + } else if (this._opcode > 0x07 && this._opcode < 0x0b) { + if (!this._fin) { + this._loop = false; + return error(RangeError, 'FIN must be set', true, 1002); + } + + if (compressed) { + this._loop = false; + return error(RangeError, 'RSV1 must be clear', true, 1002); + } + + if (this._payloadLength > 0x7d) { + this._loop = false; + return error( + RangeError, + `invalid payload length ${this._payloadLength}`, + true, + 1002 + ); + } + } else { + this._loop = false; + return error(RangeError, `invalid opcode ${this._opcode}`, true, 1002); + } + + if (!this._fin && !this._fragmented) this._fragmented = this._opcode; + this._masked = (buf[1] & 0x80) === 0x80; + + if (this._payloadLength === 126) this._state = GET_PAYLOAD_LENGTH_16; + else if (this._payloadLength === 127) this._state = GET_PAYLOAD_LENGTH_64; + else return this.haveLength(); + } + + /** + * Gets extended payload length (7+16). + * + * @return {(RangeError|undefined)} A possible error + * @private + */ + getPayloadLength16 () { + if (this._bufferedBytes < 2) { + this._loop = false; + return; + } + + this._payloadLength = this.consume(2).readUInt16BE(0); + return this.haveLength(); + } + + /** + * Gets extended payload length (7+64). + * + * @return {(RangeError|undefined)} A possible error + * @private + */ + getPayloadLength64 () { + if (this._bufferedBytes < 8) { + this._loop = false; + return; + } + + const buf = this.consume(8); + const num = buf.readUInt32BE(0); + + // + // The maximum safe integer in JavaScript is 2^53 - 1. An error is returned + // if payload length is greater than this number. + // + if (num > Math.pow(2, 53 - 32) - 1) { + this._loop = false; + return error( + RangeError, + 'Unsupported WebSocket frame: payload length > 2^53 - 1', + false, + 1009 + ); + } + + this._payloadLength = num * Math.pow(2, 32) + buf.readUInt32BE(4); + return this.haveLength(); + } + + /** + * Payload length has been read. + * + * @return {(RangeError|undefined)} A possible error + * @private + */ + haveLength () { + if (this._payloadLength && this._opcode < 0x08) { + this._totalPayloadLength += this._payloadLength; + if (this._totalPayloadLength > this._maxPayload && this._maxPayload > 0) { + this._loop = false; + return error(RangeError, 'Max payload size exceeded', false, 1009); + } + } + + if (this._masked) this._state = GET_MASK; + else this._state = GET_DATA; + } + + /** + * Reads mask bytes. + * + * @private + */ + getMask () { + if (this._bufferedBytes < 4) { + this._loop = false; + return; + } + + this._mask = this.consume(4); + this._state = GET_DATA; + } + + /** + * Reads data bytes. + * + * @param {Function} cb Callback + * @return {(Error|RangeError|undefined)} A possible error + * @private + */ + getData (cb) { + var data = constants.EMPTY_BUFFER; + + if (this._payloadLength) { + if (this._bufferedBytes < this._payloadLength) { + this._loop = false; + return; + } + + data = this.consume(this._payloadLength); + if (this._masked) bufferUtil.unmask(data, this._mask); + } + + if (this._opcode > 0x07) return this.controlMessage(data); + + if (this._compressed) { + this._state = INFLATING; + this.decompress(data, cb); + return; + } + + if (data.length) { + // + // This message is not compressed so its lenght is the sum of the payload + // length of all fragments. + // + this._messageLength = this._totalPayloadLength; + this._fragments.push(data); + } + + return this.dataMessage(); + } + + /** + * Decompresses data. + * + * @param {Buffer} data Compressed data + * @param {Function} cb Callback + * @private + */ + decompress (data, cb) { + const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName]; + + perMessageDeflate.decompress(data, this._fin, (err, buf) => { + if (err) return cb(err); + + if (buf.length) { + this._messageLength += buf.length; + if (this._messageLength > this._maxPayload && this._maxPayload > 0) { + return cb(error(RangeError, 'Max payload size exceeded', false, 1009)); + } + + this._fragments.push(buf); + } + + const er = this.dataMessage(); + if (er) return cb(er); + + this.startLoop(cb); + }); + } + + /** + * Handles a data message. + * + * @return {(Error|undefined)} A possible error + * @private + */ + dataMessage () { + if (this._fin) { + const messageLength = this._messageLength; + const fragments = this._fragments; + + this._totalPayloadLength = 0; + this._messageLength = 0; + this._fragmented = 0; + this._fragments = []; + + if (this._opcode === 2) { + var data; + + if (this._binaryType === 'nodebuffer') { + data = toBuffer(fragments, messageLength); + } else if (this._binaryType === 'arraybuffer') { + data = toArrayBuffer(toBuffer(fragments, messageLength)); + } else { + data = fragments; + } + + this.emit('message', data); + } else { + const buf = toBuffer(fragments, messageLength); + + if (!validation.isValidUTF8(buf)) { + this._loop = false; + return error(Error, 'invalid UTF-8 sequence', true, 1007); + } + + this.emit('message', buf.toString()); + } + } + + this._state = GET_INFO; + } + + /** + * Handles a control message. + * + * @param {Buffer} data Data to handle + * @return {(Error|RangeError|undefined)} A possible error + * @private + */ + controlMessage (data) { + if (this._opcode === 0x08) { + this._loop = false; + + if (data.length === 0) { + this.emit('conclude', 1005, ''); + this.end(); + } else if (data.length === 1) { + return error(RangeError, 'invalid payload length 1', true, 1002); + } else { + const code = data.readUInt16BE(0); + + if (!validation.isValidStatusCode(code)) { + return error(RangeError, `invalid status code ${code}`, true, 1002); + } + + const buf = data.slice(2); + + if (!validation.isValidUTF8(buf)) { + return error(Error, 'invalid UTF-8 sequence', true, 1007); + } + + this.emit('conclude', code, buf.toString()); + this.end(); + } + + return; + } + + if (this._opcode === 0x09) this.emit('ping', data); + else this.emit('pong', data); + + this._state = GET_INFO; + } +} + +module.exports = Receiver; + +/** + * Builds an error object. + * + * @param {(Error|RangeError)} ErrorCtor The error constructor + * @param {String} message The error message + * @param {Boolean} prefix Specifies whether or not to add a default prefix to + * `message` + * @param {Number} statusCode The status code + * @return {(Error|RangeError)} The error + * @private + */ +function error (ErrorCtor, message, prefix, statusCode) { + const err = new ErrorCtor( + prefix ? `Invalid WebSocket frame: ${message}` : message + ); + + Error.captureStackTrace(err, error); + err[constants.kStatusCode] = statusCode; + return err; +} + +/** + * Makes a buffer from a list of fragments. + * + * @param {Buffer[]} fragments The list of fragments composing the message + * @param {Number} messageLength The length of the message + * @return {Buffer} + * @private + */ +function toBuffer (fragments, messageLength) { + if (fragments.length === 1) return fragments[0]; + if (fragments.length > 1) return bufferUtil.concat(fragments, messageLength); + return constants.EMPTY_BUFFER; +} + +/** + * Converts a buffer to an `ArrayBuffer`. + * + * @param {Buffer} The buffer to convert + * @return {ArrayBuffer} Converted buffer + */ +function toArrayBuffer (buf) { + if (buf.byteOffset === 0 && buf.byteLength === buf.buffer.byteLength) { + return buf.buffer; + } + + return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); +} diff --git a/express-server/node_modules/ws/lib/sender.js b/express-server/node_modules/ws/lib/sender.js new file mode 100644 index 00000000..060e5539 --- /dev/null +++ b/express-server/node_modules/ws/lib/sender.js @@ -0,0 +1,401 @@ +'use strict'; + +const crypto = require('crypto'); + +const PerMessageDeflate = require('./permessage-deflate'); +const bufferUtil = require('./buffer-util'); +const validation = require('./validation'); +const constants = require('./constants'); + +/** + * HyBi Sender implementation. + */ +class Sender { + /** + * Creates a Sender instance. + * + * @param {net.Socket} socket The connection socket + * @param {Object} extensions An object containing the negotiated extensions + */ + constructor (socket, extensions) { + this._extensions = extensions || {}; + this._socket = socket; + + this._firstFragment = true; + this._compress = false; + + this._bufferedBytes = 0; + this._deflating = false; + this._queue = []; + } + + /** + * Frames a piece of data according to the HyBi WebSocket protocol. + * + * @param {Buffer} data The data to frame + * @param {Object} options Options object + * @param {Number} options.opcode The opcode + * @param {Boolean} options.readOnly Specifies whether `data` can be modified + * @param {Boolean} options.fin Specifies whether or not to set the FIN bit + * @param {Boolean} options.mask Specifies whether or not to mask `data` + * @param {Boolean} options.rsv1 Specifies whether or not to set the RSV1 bit + * @return {Buffer[]} The framed data as a list of `Buffer` instances + * @public + */ + static frame (data, options) { + const merge = data.length < 1024 || (options.mask && options.readOnly); + var offset = options.mask ? 6 : 2; + var payloadLength = data.length; + + if (data.length >= 65536) { + offset += 8; + payloadLength = 127; + } else if (data.length > 125) { + offset += 2; + payloadLength = 126; + } + + const target = Buffer.allocUnsafe(merge ? data.length + offset : offset); + + target[0] = options.fin ? options.opcode | 0x80 : options.opcode; + if (options.rsv1) target[0] |= 0x40; + + if (payloadLength === 126) { + target.writeUInt16BE(data.length, 2); + } else if (payloadLength === 127) { + target.writeUInt32BE(0, 2); + target.writeUInt32BE(data.length, 6); + } + + if (!options.mask) { + target[1] = payloadLength; + if (merge) { + data.copy(target, offset); + return [target]; + } + + return [target, data]; + } + + const mask = crypto.randomBytes(4); + + target[1] = payloadLength | 0x80; + target[offset - 4] = mask[0]; + target[offset - 3] = mask[1]; + target[offset - 2] = mask[2]; + target[offset - 1] = mask[3]; + + if (merge) { + bufferUtil.mask(data, mask, target, offset, data.length); + return [target]; + } + + bufferUtil.mask(data, mask, data, 0, data.length); + return [target, data]; + } + + /** + * Sends a close message to the other peer. + * + * @param {(Number|undefined)} code The status code component of the body + * @param {String} data The message component of the body + * @param {Boolean} mask Specifies whether or not to mask the message + * @param {Function} cb Callback + * @public + */ + close (code, data, mask, cb) { + var buf; + + if (code === undefined) { + buf = constants.EMPTY_BUFFER; + } else if (typeof code !== 'number' || !validation.isValidStatusCode(code)) { + throw new TypeError('First argument must be a valid error code number'); + } else if (data === undefined || data === '') { + buf = Buffer.allocUnsafe(2); + buf.writeUInt16BE(code, 0); + } else { + buf = Buffer.allocUnsafe(2 + Buffer.byteLength(data)); + buf.writeUInt16BE(code, 0); + buf.write(data, 2); + } + + if (this._deflating) { + this.enqueue([this.doClose, buf, mask, cb]); + } else { + this.doClose(buf, mask, cb); + } + } + + /** + * Frames and sends a close message. + * + * @param {Buffer} data The message to send + * @param {Boolean} mask Specifies whether or not to mask `data` + * @param {Function} cb Callback + * @private + */ + doClose (data, mask, cb) { + this.sendFrame(Sender.frame(data, { + fin: true, + rsv1: false, + opcode: 0x08, + mask, + readOnly: false + }), cb); + } + + /** + * Sends a ping message to the other peer. + * + * @param {*} data The message to send + * @param {Boolean} mask Specifies whether or not to mask `data` + * @param {Function} cb Callback + * @public + */ + ping (data, mask, cb) { + var readOnly = true; + + if (!Buffer.isBuffer(data)) { + if (data instanceof ArrayBuffer) { + data = Buffer.from(data); + } else if (ArrayBuffer.isView(data)) { + data = viewToBuffer(data); + } else { + data = Buffer.from(data); + readOnly = false; + } + } + + if (this._deflating) { + this.enqueue([this.doPing, data, mask, readOnly, cb]); + } else { + this.doPing(data, mask, readOnly, cb); + } + } + + /** + * Frames and sends a ping message. + * + * @param {*} data The message to send + * @param {Boolean} mask Specifies whether or not to mask `data` + * @param {Boolean} readOnly Specifies whether `data` can be modified + * @param {Function} cb Callback + * @private + */ + doPing (data, mask, readOnly, cb) { + this.sendFrame(Sender.frame(data, { + fin: true, + rsv1: false, + opcode: 0x09, + mask, + readOnly + }), cb); + } + + /** + * Sends a pong message to the other peer. + * + * @param {*} data The message to send + * @param {Boolean} mask Specifies whether or not to mask `data` + * @param {Function} cb Callback + * @public + */ + pong (data, mask, cb) { + var readOnly = true; + + if (!Buffer.isBuffer(data)) { + if (data instanceof ArrayBuffer) { + data = Buffer.from(data); + } else if (ArrayBuffer.isView(data)) { + data = viewToBuffer(data); + } else { + data = Buffer.from(data); + readOnly = false; + } + } + + if (this._deflating) { + this.enqueue([this.doPong, data, mask, readOnly, cb]); + } else { + this.doPong(data, mask, readOnly, cb); + } + } + + /** + * Frames and sends a pong message. + * + * @param {*} data The message to send + * @param {Boolean} mask Specifies whether or not to mask `data` + * @param {Boolean} readOnly Specifies whether `data` can be modified + * @param {Function} cb Callback + * @private + */ + doPong (data, mask, readOnly, cb) { + this.sendFrame(Sender.frame(data, { + fin: true, + rsv1: false, + opcode: 0x0a, + mask, + readOnly + }), cb); + } + + /** + * Sends a data message to the other peer. + * + * @param {*} data The message to send + * @param {Object} options Options object + * @param {Boolean} options.compress Specifies whether or not to compress `data` + * @param {Boolean} options.binary Specifies whether `data` is binary or text + * @param {Boolean} options.fin Specifies whether the fragment is the last one + * @param {Boolean} options.mask Specifies whether or not to mask `data` + * @param {Function} cb Callback + * @public + */ + send (data, options, cb) { + var opcode = options.binary ? 2 : 1; + var rsv1 = options.compress; + var readOnly = true; + + if (!Buffer.isBuffer(data)) { + if (data instanceof ArrayBuffer) { + data = Buffer.from(data); + } else if (ArrayBuffer.isView(data)) { + data = viewToBuffer(data); + } else { + data = Buffer.from(data); + readOnly = false; + } + } + + const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName]; + + if (this._firstFragment) { + this._firstFragment = false; + if (rsv1 && perMessageDeflate) { + rsv1 = data.length >= perMessageDeflate._threshold; + } + this._compress = rsv1; + } else { + rsv1 = false; + opcode = 0; + } + + if (options.fin) this._firstFragment = true; + + if (perMessageDeflate) { + const opts = { + fin: options.fin, + rsv1, + opcode, + mask: options.mask, + readOnly + }; + + if (this._deflating) { + this.enqueue([this.dispatch, data, this._compress, opts, cb]); + } else { + this.dispatch(data, this._compress, opts, cb); + } + } else { + this.sendFrame(Sender.frame(data, { + fin: options.fin, + rsv1: false, + opcode, + mask: options.mask, + readOnly + }), cb); + } + } + + /** + * Dispatches a data message. + * + * @param {Buffer} data The message to send + * @param {Boolean} compress Specifies whether or not to compress `data` + * @param {Object} options Options object + * @param {Number} options.opcode The opcode + * @param {Boolean} options.readOnly Specifies whether `data` can be modified + * @param {Boolean} options.fin Specifies whether or not to set the FIN bit + * @param {Boolean} options.mask Specifies whether or not to mask `data` + * @param {Boolean} options.rsv1 Specifies whether or not to set the RSV1 bit + * @param {Function} cb Callback + * @private + */ + dispatch (data, compress, options, cb) { + if (!compress) { + this.sendFrame(Sender.frame(data, options), cb); + return; + } + + const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName]; + + this._deflating = true; + perMessageDeflate.compress(data, options.fin, (_, buf) => { + options.readOnly = false; + this.sendFrame(Sender.frame(buf, options), cb); + this._deflating = false; + this.dequeue(); + }); + } + + /** + * Executes queued send operations. + * + * @private + */ + dequeue () { + while (!this._deflating && this._queue.length) { + const params = this._queue.shift(); + + this._bufferedBytes -= params[1].length; + params[0].apply(this, params.slice(1)); + } + } + + /** + * Enqueues a send operation. + * + * @param {Array} params Send operation parameters. + * @private + */ + enqueue (params) { + this._bufferedBytes += params[1].length; + this._queue.push(params); + } + + /** + * Sends a frame. + * + * @param {Buffer[]} list The frame to send + * @param {Function} cb Callback + * @private + */ + sendFrame (list, cb) { + if (list.length === 2) { + this._socket.write(list[0]); + this._socket.write(list[1], cb); + } else { + this._socket.write(list[0], cb); + } + } +} + +module.exports = Sender; + +/** + * Converts an `ArrayBuffer` view into a buffer. + * + * @param {(DataView|TypedArray)} view The view to convert + * @return {Buffer} Converted view + * @private + */ +function viewToBuffer (view) { + const buf = Buffer.from(view.buffer); + + if (view.byteLength !== view.buffer.byteLength) { + return buf.slice(view.byteOffset, view.byteOffset + view.byteLength); + } + + return buf; +} diff --git a/express-server/node_modules/ws/lib/validation.js b/express-server/node_modules/ws/lib/validation.js new file mode 100644 index 00000000..06269fcf --- /dev/null +++ b/express-server/node_modules/ws/lib/validation.js @@ -0,0 +1,29 @@ +'use strict'; + +try { + const isValidUTF8 = require('utf-8-validate'); + + exports.isValidUTF8 = typeof isValidUTF8 === 'object' + ? isValidUTF8.Validation.isValidUTF8 // utf-8-validate@<3.0.0 + : isValidUTF8; +} catch (e) /* istanbul ignore next */ { + exports.isValidUTF8 = () => true; +} + +/** + * Checks if a status code is allowed in a close frame. + * + * @param {Number} code The status code + * @return {Boolean} `true` if the status code is valid, else `false` + * @public + */ +exports.isValidStatusCode = (code) => { + return ( + (code >= 1000 && + code <= 1013 && + code !== 1004 && + code !== 1005 && + code !== 1006) || + (code >= 3000 && code <= 4999) + ); +}; diff --git a/express-server/node_modules/ws/lib/websocket-server.js b/express-server/node_modules/ws/lib/websocket-server.js new file mode 100644 index 00000000..70513edf --- /dev/null +++ b/express-server/node_modules/ws/lib/websocket-server.js @@ -0,0 +1,357 @@ +'use strict'; + +const EventEmitter = require('events'); +const crypto = require('crypto'); +const http = require('http'); +const url = require('url'); + +const PerMessageDeflate = require('./permessage-deflate'); +const extension = require('./extension'); +const constants = require('./constants'); +const WebSocket = require('./websocket'); + +/** + * Class representing a WebSocket server. + * + * @extends EventEmitter + */ +class WebSocketServer extends EventEmitter { + /** + * Create a `WebSocketServer` instance. + * + * @param {Object} options Configuration options + * @param {String} options.host The hostname where to bind the server + * @param {Number} options.port The port where to bind the server + * @param {http.Server} options.server A pre-created HTTP/S server to use + * @param {Function} options.verifyClient An hook to reject connections + * @param {Function} options.handleProtocols An hook to handle protocols + * @param {String} options.path Accept only connections matching this path + * @param {Boolean} options.noServer Enable no server mode + * @param {Boolean} options.clientTracking Specifies whether or not to track clients + * @param {(Boolean|Object)} options.perMessageDeflate Enable/disable permessage-deflate + * @param {Number} options.maxPayload The maximum allowed message size + * @param {Function} callback A listener for the `listening` event + */ + constructor (options, callback) { + super(); + + options = Object.assign({ + maxPayload: 100 * 1024 * 1024, + perMessageDeflate: false, + handleProtocols: null, + clientTracking: true, + verifyClient: null, + noServer: false, + backlog: null, // use default (511 as implemented in net.js) + server: null, + host: null, + path: null, + port: null + }, options); + + if (options.port == null && !options.server && !options.noServer) { + throw new TypeError( + 'One of the "port", "server", or "noServer" options must be specified' + ); + } + + if (options.port != null) { + this._server = http.createServer((req, res) => { + const body = http.STATUS_CODES[426]; + + res.writeHead(426, { + 'Content-Length': body.length, + 'Content-Type': 'text/plain' + }); + res.end(body); + }); + this._server.listen(options.port, options.host, options.backlog, callback); + } else if (options.server) { + this._server = options.server; + } + + if (this._server) { + this._removeListeners = addListeners(this._server, { + listening: this.emit.bind(this, 'listening'), + error: this.emit.bind(this, 'error'), + upgrade: (req, socket, head) => { + this.handleUpgrade(req, socket, head, (ws) => { + this.emit('connection', ws, req); + }); + } + }); + } + + if (options.perMessageDeflate === true) options.perMessageDeflate = {}; + if (options.clientTracking) this.clients = new Set(); + this.options = options; + } + + /** + * Returns the bound address, the address family name, and port of the server + * as reported by the operating system if listening on an IP socket. + * If the server is listening on a pipe or UNIX domain socket, the name is + * returned as a string. + * + * @return {(Object|String|null)} The address of the server + * @public + */ + address () { + if (this.options.noServer) { + throw new Error('The server is operating in "noServer" mode'); + } + + if (!this._server) return null; + return this._server.address(); + } + + /** + * Close the server. + * + * @param {Function} cb Callback + * @public + */ + close (cb) { + // + // Terminate all associated clients. + // + if (this.clients) { + for (const client of this.clients) client.terminate(); + } + + const server = this._server; + + if (server) { + this._removeListeners(); + this._removeListeners = this._server = null; + + // + // Close the http server if it was internally created. + // + if (this.options.port != null) return server.close(cb); + } + + if (cb) cb(); + } + + /** + * See if a given request should be handled by this server instance. + * + * @param {http.IncomingMessage} req Request object to inspect + * @return {Boolean} `true` if the request is valid, else `false` + * @public + */ + shouldHandle (req) { + if (this.options.path && url.parse(req.url).pathname !== this.options.path) { + return false; + } + + return true; + } + + /** + * Handle a HTTP Upgrade request. + * + * @param {http.IncomingMessage} req The request object + * @param {net.Socket} socket The network socket between the server and client + * @param {Buffer} head The first packet of the upgraded stream + * @param {Function} cb Callback + * @public + */ + handleUpgrade (req, socket, head, cb) { + socket.on('error', socketOnError); + + const version = +req.headers['sec-websocket-version']; + const extensions = {}; + + if ( + req.method !== 'GET' || req.headers.upgrade.toLowerCase() !== 'websocket' || + !req.headers['sec-websocket-key'] || (version !== 8 && version !== 13) || + !this.shouldHandle(req) + ) { + return abortHandshake(socket, 400); + } + + if (this.options.perMessageDeflate) { + const perMessageDeflate = new PerMessageDeflate( + this.options.perMessageDeflate, + true, + this.options.maxPayload + ); + + try { + const offers = extension.parse( + req.headers['sec-websocket-extensions'] + ); + + if (offers[PerMessageDeflate.extensionName]) { + perMessageDeflate.accept(offers[PerMessageDeflate.extensionName]); + extensions[PerMessageDeflate.extensionName] = perMessageDeflate; + } + } catch (err) { + return abortHandshake(socket, 400); + } + } + + // + // Optionally call external client verification handler. + // + if (this.options.verifyClient) { + const info = { + origin: req.headers[`${version === 8 ? 'sec-websocket-origin' : 'origin'}`], + secure: !!(req.connection.authorized || req.connection.encrypted), + req + }; + + if (this.options.verifyClient.length === 2) { + this.options.verifyClient(info, (verified, code, message, headers) => { + if (!verified) { + return abortHandshake(socket, code || 401, message, headers); + } + + this.completeUpgrade(extensions, req, socket, head, cb); + }); + return; + } + + if (!this.options.verifyClient(info)) return abortHandshake(socket, 401); + } + + this.completeUpgrade(extensions, req, socket, head, cb); + } + + /** + * Upgrade the connection to WebSocket. + * + * @param {Object} extensions The accepted extensions + * @param {http.IncomingMessage} req The request object + * @param {net.Socket} socket The network socket between the server and client + * @param {Buffer} head The first packet of the upgraded stream + * @param {Function} cb Callback + * @private + */ + completeUpgrade (extensions, req, socket, head, cb) { + // + // Destroy the socket if the client has already sent a FIN packet. + // + if (!socket.readable || !socket.writable) return socket.destroy(); + + const key = crypto.createHash('sha1') + .update(req.headers['sec-websocket-key'] + constants.GUID, 'binary') + .digest('base64'); + + const headers = [ + 'HTTP/1.1 101 Switching Protocols', + 'Upgrade: websocket', + 'Connection: Upgrade', + `Sec-WebSocket-Accept: ${key}` + ]; + + const ws = new WebSocket(null); + var protocol = req.headers['sec-websocket-protocol']; + + if (protocol) { + protocol = protocol.trim().split(/ *, */); + + // + // Optionally call external protocol selection handler. + // + if (this.options.handleProtocols) { + protocol = this.options.handleProtocols(protocol, req); + } else { + protocol = protocol[0]; + } + + if (protocol) { + headers.push(`Sec-WebSocket-Protocol: ${protocol}`); + ws.protocol = protocol; + } + } + + if (extensions[PerMessageDeflate.extensionName]) { + const params = extensions[PerMessageDeflate.extensionName].params; + const value = extension.format({ + [PerMessageDeflate.extensionName]: [params] + }); + headers.push(`Sec-WebSocket-Extensions: ${value}`); + ws._extensions = extensions; + } + + // + // Allow external modification/inspection of handshake headers. + // + this.emit('headers', headers, req); + + socket.write(headers.concat('\r\n').join('\r\n')); + socket.removeListener('error', socketOnError); + + ws.setSocket(socket, head, this.options.maxPayload); + + if (this.clients) { + this.clients.add(ws); + ws.on('close', () => this.clients.delete(ws)); + } + + cb(ws); + } +} + +module.exports = WebSocketServer; + +/** + * Add event listeners on an `EventEmitter` using a map of + * pairs. + * + * @param {EventEmitter} server The event emitter + * @param {Object.} map The listeners to add + * @return {Function} A function that will remove the added listeners when called + * @private + */ +function addListeners (server, map) { + for (const event of Object.keys(map)) server.on(event, map[event]); + + return function removeListeners () { + for (const event of Object.keys(map)) { + server.removeListener(event, map[event]); + } + }; +} + +/** + * Handle premature socket errors. + * + * @private + */ +function socketOnError () { + this.destroy(); +} + +/** + * Close the connection when preconditions are not fulfilled. + * + * @param {net.Socket} socket The socket of the upgrade request + * @param {Number} code The HTTP response status code + * @param {String} [message] The HTTP response body + * @param {Object} [headers] Additional HTTP response headers + * @private + */ +function abortHandshake (socket, code, message, headers) { + if (socket.writable) { + message = message || http.STATUS_CODES[code]; + headers = Object.assign({ + 'Connection': 'close', + 'Content-type': 'text/html', + 'Content-Length': Buffer.byteLength(message) + }, headers); + + socket.write( + `HTTP/1.1 ${code} ${http.STATUS_CODES[code]}\r\n` + + Object.keys(headers).map(h => `${h}: ${headers[h]}`).join('\r\n') + + '\r\n\r\n' + + message + ); + } + + socket.removeListener('error', socketOnError); + socket.destroy(); +} diff --git a/express-server/node_modules/ws/lib/websocket.js b/express-server/node_modules/ws/lib/websocket.js new file mode 100644 index 00000000..f2bdf0d7 --- /dev/null +++ b/express-server/node_modules/ws/lib/websocket.js @@ -0,0 +1,828 @@ +'use strict'; + +const EventEmitter = require('events'); +const crypto = require('crypto'); +const https = require('https'); +const http = require('http'); +const net = require('net'); +const tls = require('tls'); +const url = require('url'); + +const PerMessageDeflate = require('./permessage-deflate'); +const EventTarget = require('./event-target'); +const extension = require('./extension'); +const constants = require('./constants'); +const Receiver = require('./receiver'); +const Sender = require('./sender'); + +const readyStates = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED']; +const kWebSocket = constants.kWebSocket; +const protocolVersions = [8, 13]; +const closeTimeout = 30 * 1000; // Allow 30 seconds to terminate the connection cleanly. + +/** + * Class representing a WebSocket. + * + * @extends EventEmitter + */ +class WebSocket extends EventEmitter { + /** + * Create a new `WebSocket`. + * + * @param {(String|url.Url|url.URL)} address The URL to which to connect + * @param {(String|String[])} protocols The subprotocols + * @param {Object} options Connection options + */ + constructor (address, protocols, options) { + super(); + + this.readyState = WebSocket.CONNECTING; + this.protocol = ''; + + this._binaryType = constants.BINARY_TYPES[0]; + this._closeFrameReceived = false; + this._closeFrameSent = false; + this._closeMessage = ''; + this._closeTimer = null; + this._closeCode = 1006; + this._extensions = {}; + this._isServer = true; + this._receiver = null; + this._sender = null; + this._socket = null; + + if (address !== null) { + if (Array.isArray(protocols)) { + protocols = protocols.join(', '); + } else if (typeof protocols === 'object' && protocols !== null) { + options = protocols; + protocols = undefined; + } + + initAsClient.call(this, address, protocols, options); + } + } + + get CONNECTING () { return WebSocket.CONNECTING; } + get CLOSING () { return WebSocket.CLOSING; } + get CLOSED () { return WebSocket.CLOSED; } + get OPEN () { return WebSocket.OPEN; } + + /** + * This deviates from the WHATWG interface since ws doesn't support the required + * default "blob" type (instead we define a custom "nodebuffer" type). + * + * @type {String} + */ + get binaryType () { + return this._binaryType; + } + + set binaryType (type) { + if (constants.BINARY_TYPES.indexOf(type) < 0) return; + + this._binaryType = type; + + // + // Allow to change `binaryType` on the fly. + // + if (this._receiver) this._receiver._binaryType = type; + } + + /** + * @type {Number} + */ + get bufferedAmount () { + if (!this._socket) return 0; + + // + // `socket.bufferSize` is `undefined` if the socket is closed. + // + return (this._socket.bufferSize || 0) + this._sender._bufferedBytes; + } + + /** + * @type {String} + */ + get extensions () { + return Object.keys(this._extensions).join(); + } + + /** + * Set up the socket and the internal resources. + * + * @param {net.Socket} socket The network socket between the server and client + * @param {Buffer} head The first packet of the upgraded stream + * @param {Number} maxPayload The maximum allowed message size + * @private + */ + setSocket (socket, head, maxPayload) { + const receiver = new Receiver( + this._binaryType, + this._extensions, + maxPayload + ); + + this._sender = new Sender(socket, this._extensions); + this._receiver = receiver; + this._socket = socket; + + receiver[kWebSocket] = this; + socket[kWebSocket] = this; + + receiver.on('conclude', receiverOnConclude); + receiver.on('drain', receiverOnDrain); + receiver.on('error', receiverOnError); + receiver.on('message', receiverOnMessage); + receiver.on('ping', receiverOnPing); + receiver.on('pong', receiverOnPong); + + socket.setTimeout(0); + socket.setNoDelay(); + + if (head.length > 0) socket.unshift(head); + + socket.on('close', socketOnClose); + socket.on('data', socketOnData); + socket.on('end', socketOnEnd); + socket.on('error', socketOnError); + + this.readyState = WebSocket.OPEN; + this.emit('open'); + } + + /** + * Emit the `'close'` event. + * + * @private + */ + emitClose () { + this.readyState = WebSocket.CLOSED; + + if (!this._socket) { + this.emit('close', this._closeCode, this._closeMessage); + return; + } + + if (this._extensions[PerMessageDeflate.extensionName]) { + this._extensions[PerMessageDeflate.extensionName].cleanup(); + } + + this._receiver.removeAllListeners(); + this.emit('close', this._closeCode, this._closeMessage); + } + + /** + * Start a closing handshake. + * + * +----------+ +-----------+ +----------+ + * - - -|ws.close()|-->|close frame|-->|ws.close()|- - - + * | +----------+ +-----------+ +----------+ | + * +----------+ +-----------+ | + * CLOSING |ws.close()|<--|close frame|<--+-----+ CLOSING + * +----------+ +-----------+ | + * | | | +---+ | + * +------------------------+-->|fin| - - - - + * | +---+ | +---+ + * - - - - -|fin|<---------------------+ + * +---+ + * + * @param {Number} code Status code explaining why the connection is closing + * @param {String} data A string explaining why the connection is closing + * @public + */ + close (code, data) { + if (this.readyState === WebSocket.CLOSED) return; + if (this.readyState === WebSocket.CONNECTING) { + const msg = 'WebSocket was closed before the connection was established'; + return abortHandshake(this, this._req, msg); + } + + if (this.readyState === WebSocket.CLOSING) { + if (this._closeFrameSent && this._closeFrameReceived) this._socket.end(); + return; + } + + this.readyState = WebSocket.CLOSING; + this._sender.close(code, data, !this._isServer, (err) => { + // + // This error is handled by the `'error'` listener on the socket. We only + // want to know if the close frame has been sent here. + // + if (err) return; + + this._closeFrameSent = true; + + if (this._socket.writable) { + if (this._closeFrameReceived) this._socket.end(); + + // + // Ensure that the connection is closed even if the closing handshake + // fails. + // + this._closeTimer = setTimeout( + this._socket.destroy.bind(this._socket), + closeTimeout + ); + } + }); + } + + /** + * Send a ping. + * + * @param {*} data The data to send + * @param {Boolean} mask Indicates whether or not to mask `data` + * @param {Function} cb Callback which is executed when the ping is sent + * @public + */ + ping (data, mask, cb) { + if (typeof data === 'function') { + cb = data; + data = mask = undefined; + } else if (typeof mask === 'function') { + cb = mask; + mask = undefined; + } + + if (this.readyState !== WebSocket.OPEN) { + const err = new Error( + `WebSocket is not open: readyState ${this.readyState} ` + + `(${readyStates[this.readyState]})` + ); + + if (cb) return cb(err); + throw err; + } + + if (typeof data === 'number') data = data.toString(); + if (mask === undefined) mask = !this._isServer; + this._sender.ping(data || constants.EMPTY_BUFFER, mask, cb); + } + + /** + * Send a pong. + * + * @param {*} data The data to send + * @param {Boolean} mask Indicates whether or not to mask `data` + * @param {Function} cb Callback which is executed when the pong is sent + * @public + */ + pong (data, mask, cb) { + if (typeof data === 'function') { + cb = data; + data = mask = undefined; + } else if (typeof mask === 'function') { + cb = mask; + mask = undefined; + } + + if (this.readyState !== WebSocket.OPEN) { + const err = new Error( + `WebSocket is not open: readyState ${this.readyState} ` + + `(${readyStates[this.readyState]})` + ); + + if (cb) return cb(err); + throw err; + } + + if (typeof data === 'number') data = data.toString(); + if (mask === undefined) mask = !this._isServer; + this._sender.pong(data || constants.EMPTY_BUFFER, mask, cb); + } + + /** + * Send a data message. + * + * @param {*} data The message to send + * @param {Object} options Options object + * @param {Boolean} options.compress Specifies whether or not to compress `data` + * @param {Boolean} options.binary Specifies whether `data` is binary or text + * @param {Boolean} options.fin Specifies whether the fragment is the last one + * @param {Boolean} options.mask Specifies whether or not to mask `data` + * @param {Function} cb Callback which is executed when data is written out + * @public + */ + send (data, options, cb) { + if (typeof options === 'function') { + cb = options; + options = {}; + } + + if (this.readyState !== WebSocket.OPEN) { + const err = new Error( + `WebSocket is not open: readyState ${this.readyState} ` + + `(${readyStates[this.readyState]})` + ); + + if (cb) return cb(err); + throw err; + } + + if (typeof data === 'number') data = data.toString(); + + const opts = Object.assign({ + binary: typeof data !== 'string', + mask: !this._isServer, + compress: true, + fin: true + }, options); + + if (!this._extensions[PerMessageDeflate.extensionName]) { + opts.compress = false; + } + + this._sender.send(data || constants.EMPTY_BUFFER, opts, cb); + } + + /** + * Forcibly close the connection. + * + * @public + */ + terminate () { + if (this.readyState === WebSocket.CLOSED) return; + if (this.readyState === WebSocket.CONNECTING) { + const msg = 'WebSocket was closed before the connection was established'; + return abortHandshake(this, this._req, msg); + } + + if (this._socket) { + this.readyState = WebSocket.CLOSING; + this._socket.destroy(); + } + } +} + +readyStates.forEach((readyState, i) => { + WebSocket[readyStates[i]] = i; +}); + +// +// Add the `onopen`, `onerror`, `onclose`, and `onmessage` attributes. +// See https://html.spec.whatwg.org/multipage/comms.html#the-websocket-interface +// +['open', 'error', 'close', 'message'].forEach((method) => { + Object.defineProperty(WebSocket.prototype, `on${method}`, { + /** + * Return the listener of the event. + * + * @return {(Function|undefined)} The event listener or `undefined` + * @public + */ + get () { + const listeners = this.listeners(method); + for (var i = 0; i < listeners.length; i++) { + if (listeners[i]._listener) return listeners[i]._listener; + } + }, + /** + * Add a listener for the event. + * + * @param {Function} listener The listener to add + * @public + */ + set (listener) { + const listeners = this.listeners(method); + for (var i = 0; i < listeners.length; i++) { + // + // Remove only the listeners added via `addEventListener`. + // + if (listeners[i]._listener) this.removeListener(method, listeners[i]); + } + this.addEventListener(method, listener); + } + }); +}); + +WebSocket.prototype.addEventListener = EventTarget.addEventListener; +WebSocket.prototype.removeEventListener = EventTarget.removeEventListener; + +module.exports = WebSocket; + +/** + * Initialize a WebSocket client. + * + * @param {(String|url.Url|url.URL)} address The URL to which to connect + * @param {String} protocols The subprotocols + * @param {Object} options Connection options + * @param {(Boolean|Object)} options.perMessageDeflate Enable/disable permessage-deflate + * @param {Number} options.handshakeTimeout Timeout in milliseconds for the handshake request + * @param {Number} options.protocolVersion Value of the `Sec-WebSocket-Version` header + * @param {String} options.origin Value of the `Origin` or `Sec-WebSocket-Origin` header + * @private + */ +function initAsClient (address, protocols, options) { + options = Object.assign({ + protocolVersion: protocolVersions[1], + perMessageDeflate: true + }, options, { + createConnection: undefined, + socketPath: undefined, + hostname: undefined, + protocol: undefined, + timeout: undefined, + method: undefined, + auth: undefined, + host: undefined, + path: undefined, + port: undefined + }); + + if (protocolVersions.indexOf(options.protocolVersion) === -1) { + throw new RangeError( + `Unsupported protocol version: ${options.protocolVersion} ` + + `(supported versions: ${protocolVersions.join(', ')})` + ); + } + + this._isServer = false; + + var parsedUrl; + + if (typeof address === 'object' && address.href !== undefined) { + parsedUrl = address; + this.url = address.href; + } else { + parsedUrl = url.parse(address); + this.url = address; + } + + const isUnixSocket = parsedUrl.protocol === 'ws+unix:'; + + if (!parsedUrl.host && (!isUnixSocket || !parsedUrl.pathname)) { + throw new Error(`Invalid URL: ${this.url}`); + } + + const isSecure = parsedUrl.protocol === 'wss:' || parsedUrl.protocol === 'https:'; + const key = crypto.randomBytes(16).toString('base64'); + const httpObj = isSecure ? https : http; + const path = parsedUrl.search + ? `${parsedUrl.pathname || '/'}${parsedUrl.search}` + : parsedUrl.pathname || '/'; + var perMessageDeflate; + + options.createConnection = isSecure ? tlsConnect : netConnect; + options.port = parsedUrl.port || (isSecure ? 443 : 80); + options.host = parsedUrl.hostname.startsWith('[') + ? parsedUrl.hostname.slice(1, -1) + : parsedUrl.hostname; + options.headers = Object.assign({ + 'Sec-WebSocket-Version': options.protocolVersion, + 'Sec-WebSocket-Key': key, + 'Connection': 'Upgrade', + 'Upgrade': 'websocket' + }, options.headers); + options.path = path; + + if (options.perMessageDeflate) { + perMessageDeflate = new PerMessageDeflate( + options.perMessageDeflate !== true ? options.perMessageDeflate : {}, + false + ); + options.headers['Sec-WebSocket-Extensions'] = extension.format({ + [PerMessageDeflate.extensionName]: perMessageDeflate.offer() + }); + } + if (protocols) { + options.headers['Sec-WebSocket-Protocol'] = protocols; + } + if (options.origin) { + if (options.protocolVersion < 13) { + options.headers['Sec-WebSocket-Origin'] = options.origin; + } else { + options.headers.Origin = options.origin; + } + } + if (parsedUrl.auth) { + options.auth = parsedUrl.auth; + } else if (parsedUrl.username || parsedUrl.password) { + options.auth = `${parsedUrl.username}:${parsedUrl.password}`; + } + + if (isUnixSocket) { + const parts = path.split(':'); + + if (options.agent == null && process.versions.modules < 57) { + // + // Setting `socketPath` in conjunction with `createConnection` without an + // agent throws an error on Node.js < 8. Work around the issue by using a + // different property. + // + options._socketPath = parts[0]; + } else { + options.socketPath = parts[0]; + } + + options.path = parts[1]; + } + + var req = this._req = httpObj.get(options); + + if (options.handshakeTimeout) { + req.setTimeout( + options.handshakeTimeout, + () => abortHandshake(this, req, 'Opening handshake has timed out') + ); + } + + req.on('error', (err) => { + if (this._req.aborted) return; + + req = this._req = null; + this.readyState = WebSocket.CLOSING; + this.emit('error', err); + this.emitClose(); + }); + + req.on('response', (res) => { + if (this.emit('unexpected-response', req, res)) return; + + abortHandshake(this, req, `Unexpected server response: ${res.statusCode}`); + }); + + req.on('upgrade', (res, socket, head) => { + this.emit('upgrade', res); + + // + // The user may have closed the connection from a listener of the `upgrade` + // event. + // + if (this.readyState !== WebSocket.CONNECTING) return; + + req = this._req = null; + + const digest = crypto.createHash('sha1') + .update(key + constants.GUID, 'binary') + .digest('base64'); + + if (res.headers['sec-websocket-accept'] !== digest) { + abortHandshake(this, socket, 'Invalid Sec-WebSocket-Accept header'); + return; + } + + const serverProt = res.headers['sec-websocket-protocol']; + const protList = (protocols || '').split(/, */); + var protError; + + if (!protocols && serverProt) { + protError = 'Server sent a subprotocol but none was requested'; + } else if (protocols && !serverProt) { + protError = 'Server sent no subprotocol'; + } else if (serverProt && protList.indexOf(serverProt) === -1) { + protError = 'Server sent an invalid subprotocol'; + } + + if (protError) { + abortHandshake(this, socket, protError); + return; + } + + if (serverProt) this.protocol = serverProt; + + if (perMessageDeflate) { + try { + const extensions = extension.parse( + res.headers['sec-websocket-extensions'] + ); + + if (extensions[PerMessageDeflate.extensionName]) { + perMessageDeflate.accept( + extensions[PerMessageDeflate.extensionName] + ); + this._extensions[PerMessageDeflate.extensionName] = perMessageDeflate; + } + } catch (err) { + abortHandshake(this, socket, 'Invalid Sec-WebSocket-Extensions header'); + return; + } + } + + this.setSocket(socket, head, 0); + }); +} + +/** + * Create a `net.Socket` and initiate a connection. + * + * @param {Object} options Connection options + * @return {net.Socket} The newly created socket used to start the connection + * @private + */ +function netConnect (options) { + options.path = options.socketPath || options._socketPath || undefined; + return net.connect(options); +} + +/** + * Create a `tls.TLSSocket` and initiate a connection. + * + * @param {Object} options Connection options + * @return {tls.TLSSocket} The newly created socket used to start the connection + * @private + */ +function tlsConnect (options) { + options.path = options.socketPath || options._socketPath || undefined; + options.servername = options.servername || options.host; + return tls.connect(options); +} + +/** + * Abort the handshake and emit an error. + * + * @param {WebSocket} websocket The WebSocket instance + * @param {(http.ClientRequest|net.Socket)} stream The request to abort or the + * socket to destroy + * @param {String} message The error message + * @private + */ +function abortHandshake (websocket, stream, message) { + websocket.readyState = WebSocket.CLOSING; + + const err = new Error(message); + Error.captureStackTrace(err, abortHandshake); + + if (stream.setHeader) { + stream.abort(); + stream.once('abort', websocket.emitClose.bind(websocket)); + websocket.emit('error', err); + } else { + stream.destroy(err); + stream.once('error', websocket.emit.bind(websocket, 'error')); + stream.once('close', websocket.emitClose.bind(websocket)); + } +} + +/** + * The listener of the `Receiver` `'conclude'` event. + * + * @param {Number} code The status code + * @param {String} reason The reason for closing + * @private + */ +function receiverOnConclude (code, reason) { + const websocket = this[kWebSocket]; + + websocket._socket.removeListener('data', socketOnData); + websocket._socket.resume(); + + websocket._closeFrameReceived = true; + websocket._closeMessage = reason; + websocket._closeCode = code; + + if (code === 1005) websocket.close(); + else websocket.close(code, reason); +} + +/** + * The listener of the `Receiver` `'drain'` event. + * + * @private + */ +function receiverOnDrain () { + this[kWebSocket]._socket.resume(); +} + +/** + * The listener of the `Receiver` `'error'` event. + * + * @param {(RangeError|Error)} err The emitted error + * @private + */ +function receiverOnError (err) { + const websocket = this[kWebSocket]; + + websocket._socket.removeListener('data', socketOnData); + + websocket.readyState = WebSocket.CLOSING; + websocket._closeCode = err[constants.kStatusCode]; + websocket.emit('error', err); + websocket._socket.destroy(); +} + +/** + * The listener of the `Receiver` `'finish'` event. + * + * @private + */ +function receiverOnFinish () { + this[kWebSocket].emitClose(); +} + +/** + * The listener of the `Receiver` `'message'` event. + * + * @param {(String|Buffer|ArrayBuffer|Buffer[])} data The message + * @private + */ +function receiverOnMessage (data) { + this[kWebSocket].emit('message', data); +} + +/** + * The listener of the `Receiver` `'ping'` event. + * + * @param {Buffer} data The data included in the ping frame + * @private + */ +function receiverOnPing (data) { + const websocket = this[kWebSocket]; + + websocket.pong(data, !websocket._isServer, constants.NOOP); + websocket.emit('ping', data); +} + +/** + * The listener of the `Receiver` `'pong'` event. + * + * @param {Buffer} data The data included in the pong frame + * @private + */ +function receiverOnPong (data) { + this[kWebSocket].emit('pong', data); +} + +/** + * The listener of the `net.Socket` `'close'` event. + * + * @private + */ +function socketOnClose () { + const websocket = this[kWebSocket]; + + this.removeListener('close', socketOnClose); + this.removeListener('end', socketOnEnd); + + websocket.readyState = WebSocket.CLOSING; + + // + // The close frame might not have been received or the `'end'` event emitted, + // for example, if the socket was destroyed due to an error. Ensure that the + // `receiver` stream is closed after writing any remaining buffered data to + // it. If the readable side of the socket is in flowing mode then there is no + // buffered data as everything has been already written and `readable.read()` + // will return `null`. If instead, the socket is paused, any possible buffered + // data will be read as a single chunk and emitted synchronously in a single + // `'data'` event. + // + websocket._socket.read(); + websocket._receiver.end(); + + this.removeListener('data', socketOnData); + this[kWebSocket] = undefined; + + clearTimeout(websocket._closeTimer); + + if ( + websocket._receiver._writableState.finished || + websocket._receiver._writableState.errorEmitted + ) { + websocket.emitClose(); + } else { + websocket._receiver.on('error', receiverOnFinish); + websocket._receiver.on('finish', receiverOnFinish); + } +} + +/** + * The listener of the `net.Socket` `'data'` event. + * + * @param {Buffer} chunk A chunk of data + * @private + */ +function socketOnData (chunk) { + if (!this[kWebSocket]._receiver.write(chunk)) { + this.pause(); + } +} + +/** + * The listener of the `net.Socket` `'end'` event. + * + * @private + */ +function socketOnEnd () { + const websocket = this[kWebSocket]; + + websocket.readyState = WebSocket.CLOSING; + websocket._receiver.end(); + this.end(); +} + +/** + * The listener of the `net.Socket` `'error'` event. + * + * @private + */ +function socketOnError () { + const websocket = this[kWebSocket]; + + this.removeListener('error', socketOnError); + this.on('error', constants.NOOP); + + if (websocket) { + websocket.readyState = WebSocket.CLOSING; + this.destroy(); + } +} diff --git a/express-server/node_modules/ws/package.json b/express-server/node_modules/ws/package.json new file mode 100644 index 00000000..2a38937f --- /dev/null +++ b/express-server/node_modules/ws/package.json @@ -0,0 +1,122 @@ +{ + "_args": [ + [ + "ws@^5.2.1", + "/nodeapps/https-test/greenlock-express.js" + ] + ], + "_from": "ws@>=5.2.1 <6.0.0", + "_hasShrinkwrap": false, + "_id": "ws@5.2.2", + "_inCache": true, + "_installable": true, + "_location": "/ws", + "_nodeVersion": "10.6.0", + "_npmOperationalInternal": { + "host": "s3://npm-registry-packages", + "tmp": "tmp/ws_5.2.2_1531339098131_0.05866997625683701" + }, + "_npmUser": { + "email": "luigipinca@gmail.com", + "name": "lpinca" + }, + "_npmVersion": "6.1.0", + "_phantomChildren": {}, + "_requested": { + "name": "ws", + "raw": "ws@^5.2.1", + "rawSpec": "^5.2.1", + "scope": null, + "spec": ">=5.2.1 <6.0.0", + "type": "range" + }, + "_requiredBy": [ + "#DEV:/" + ], + "_resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "_shasum": "dffef14866b8e8dc9133582514d1befaf96e980f", + "_shrinkwrap": null, + "_spec": "ws@^5.2.1", + "_where": "/nodeapps/https-test/greenlock-express.js", + "author": { + "email": "einaros@gmail.com", + "name": "Einar Otto Stangvik", + "url": "http://2x.io" + }, + "bugs": { + "url": "https://github.com/websockets/ws/issues" + }, + "dependencies": { + "async-limiter": "~1.0.0" + }, + "description": "Simple to use, blazing fast and thoroughly tested websocket client and server for Node.js", + "devDependencies": { + "benchmark": "~2.1.2", + "bufferutil": "~3.0.0", + "eslint": "~4.19.0", + "eslint-config-standard": "~11.0.0", + "eslint-plugin-import": "~2.12.0", + "eslint-plugin-node": "~6.0.0", + "eslint-plugin-promise": "~3.8.0", + "eslint-plugin-standard": "~3.0.0", + "mocha": "~5.2.0", + "nyc": "~12.0.2", + "utf-8-validate": "~4.0.0" + }, + "directories": {}, + "dist": { + "fileCount": 14, + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbRmFaCRA9TVsSAnZWagAAZH0P/iB0EIYIHqFAJznwT4el\n8xU2FN/na7yK3k+nV0cNYD+gKdOcTphij2IJGnQBM8hG4SlPBf+NBqy7/VBo\na3cmV3Rat395nmI3lhTgb9EDMFgYRQty3ORS3KAf2KEpFFA4QlTjOttjYsCq\nZN/j3GMnsnH47RxToPE9wTyC8d+cgIfdQHLN1k+5YaN5OtBCyKIXGbl+QJli\n2YLGAU1mp+yM+CF8CV+q6aodokoF/89D8LnJ7N5LjIgYGHTohB9c/fY/7v/5\nQLqd35RTo8OXMfiujUy2EhyGP5SyiTUzttAmXuSOxG3KQTtzss0dHMBxFeXJ\nO6ZDh124WW1VJYhdPKwfaHwszfmB6a95K2Gmu7xtvlq48qMq6Rfi9WQ1/rlc\nYyeyXAX1a/ykbEza4mm9oPfZpkPKSYM4s4fYufxyG3sAz3vKaOy4MQNA6gOC\n49sJBGT7kdTlPgHuE832t9T+J8ByCGNl/o2zJDDYLq6RLZqtgaSqAWtIBaFe\neW/yEVklhm2InF8e1yAiHg4au/6OKf4PFfKpcjdKvDbMZO8fFm6VDRYqFlI5\nnF2XzxK7p86sIe+YeFqVAzc4kMGcvYzrD7RhA25n+NBbjHaYChCLibgEDG7E\n2gqUv1T9BU2ihq845gapZ9h1b7/dpfqOKZCf5kvMxZLjp/rL8msRRPd4GIw9\nPXXp\r\n=QnaD\r\n-----END PGP SIGNATURE-----\r\n", + "shasum": "dffef14866b8e8dc9133582514d1befaf96e980f", + "tarball": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "unpackedSize": 99219 + }, + "files": [ + "index.js", + "lib" + ], + "gitHead": "5d55e52529167c25f4fec35cb4753294e75bf9f2", + "homepage": "https://github.com/websockets/ws", + "keywords": [ + "HyBi", + "Push", + "RFC-6455", + "WebSocket", + "WebSockets", + "real-time" + ], + "license": "MIT", + "main": "index.js", + "maintainers": [ + { + "name": "3rdeden", + "email": "npm@3rd-Eden.com" + }, + { + "name": "einaros", + "email": "einaros@gmail.com" + }, + { + "name": "lpinca", + "email": "luigipinca@gmail.com" + }, + { + "name": "v1", + "email": "npm@3rd-Eden.com" + } + ], + "name": "ws", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git+https://github.com/websockets/ws.git" + }, + "scripts": { + "integration": "eslint . && mocha test/*.integration.js", + "lint": "eslint .", + "test": "eslint . && nyc --reporter=html --reporter=text mocha test/*.test.js" + }, + "version": "5.2.2" +} diff --git a/express-server/public/javascripts/test.js b/express-server/public/javascripts/test.js index e69de29b..9318aef2 100644 --- a/express-server/public/javascripts/test.js +++ b/express-server/public/javascripts/test.js @@ -0,0 +1,97 @@ +$(document).ready(function() { + refresh(); + + userinfo(); + + $.ajax({ + type: "POST", + url: "/group", + data: { + sl_id: "0", + name: "testgroup", + color: "orangered", + hidden: false + } + }); + + $(".btn_invite").click(function() { + $.ajax({ + type: "POST", + url: "/invite", + data: { + sl_id: 'gKrNZiA3' + } + }); + }); + + + $(document).on("click", ".btn_detail", function() { + window.location.replace("/shoppinglist_json/" + $(this).closest("tr").attr("id")); + }); + + $(".btn_add").click(function() { + $.ajax({ + type: "POST", + url: "/shoppinglist", + data: { + name: $(".name").val(), + description: $(".description").val(), + color: "red" + }, success(result) { + refresh(); + } + }); + }); + + $(document).on("click", ".btn_delete", function() { + $.ajax({ + type: "DELETE", + url: "/shoppinglist", + data: { + sl_id: $(this).closest("tr").attr("id") + }, success(result) { + refresh(); + } + }); + }); +}); + +function refresh() { + + $("tbody").empty(); + + $.ajax({ + type: "GET", + url: "/myshoppinglists", + success(data) { + for(let item of data) { + $(".tb_myshoppinglists").append("" + item.name + "" + item.description + + " forward" + + "clear"); + } + } + }); + + $.ajax({ + type: "GET", + url: "/sharedshoppinglists", + success(data) { + for(let item of data) { + $(".tb_sharedshoppinglists").append("" + item.name + "" + item.description + + " forward"); + } + } + }); +} + +function userinfo() { + $.ajax({ + type: "GET", + url: "/userinfo_json", + success(data) { + $(".userinfo").empty(); + $(".userinfo").append("Logged in as: " + data.profile.displayName); + $(".user_img").attr("src", data.profile.photos[0].value); + } + }); +} \ No newline at end of file diff --git a/express-server/test/greenlock.js b/express-server/test/greenlock.js new file mode 100644 index 00000000..c10e6038 --- /dev/null +++ b/express-server/test/greenlock.js @@ -0,0 +1,75 @@ +#!/usr/bin/env node +var Greenlock = require('../'); +var greenlock = Greenlock.create({ + version: 'draft-11' +, server: 'https://acme-staging-v02.api.letsencrypt.org/directory' +, agreeTos: true +, approvedDomains: [ 'example.com', 'www.example.com' ] +, configDir: require('path').join(require('os').tmpdir(), 'acme') + +, app: require('express')().use('/', function (req, res) { + res.setHeader('Content-Type', 'text/html; charset=utf-8'); + res.end('Hello, World!\n\n💚 🔒.js'); + }) +}); + +var server1 = greenlock.listen(5080, 5443); +server1.on('listening', function () { + console.log("### THREE 3333 - All is well server1", this.address()); + setTimeout(function () { + // so that the address() object doesn't disappear + server1.close(); + server1.unencrypted.close(); + }, 10); +}); +setTimeout(function () { + var server2 = greenlock.listen(6080, 6443, function () { + console.log("### FIVE 55555 - Started server 2!"); + setTimeout(function () { + server2.close(); + server2.unencrypted.close(); + server6.close(); + server6.unencrypted.close(); + server7.close(); + server7.unencrypted.close(); + setTimeout(function () { + // TODO greenlock needs a close event (and to listen to its server's close event) + process.exit(0); + }, 1000); + }, 1000); + }); + server2.on('listening', function () { + console.log("### FOUR 44444 - All is well server2", server2.address()); + }); +}, 1000); + +var server3 = greenlock.listen(22, 22, function () { + console.error("Error: expected to get an error when launching plain server on port 22"); +}, function () { + console.error("Error: expected to get an error when launching " + server3.type + " server on port 22"); +}); +server3.unencrypted.on('error', function () { + console.log("Success: caught expected (plain) error"); +}); +server3.on('error', function () { + console.log("Success: caught expected " + server3.type + " error"); + //server3.close(); +}); + +var server4 = greenlock.listen(7080, 7443, function () { + console.log('Success: server4: plain'); + server4.unencrypted.close(); +}, function () { + console.log('Success: server4: ' + server4.type); + server4.close(); +}); + +var server5 = greenlock.listen(10080, 10443, function () { + console.log("Server 5 with one fn", this.address()); + server5.close(); + server5.unencrypted.close(); +}); + +var server6 = greenlock.listen('[::]:11080', '[::1]:11443'); + +var server7 = greenlock.listen('/tmp/gl.plain.sock', '/tmp/gl.sec.sock');