From af29d21c51832b4004830d50d66692c8a7e697a8 Mon Sep 17 00:00:00 2001 From: Bryan Yehuda Date: Fri, 27 Nov 2020 22:29:02 +0700 Subject: [PATCH] Initial Commit --- hosting.txt | 1 + images/Color Hunt Palette 212984.png | Bin 0 -> 17628 bytes images/favicon.ico | Bin 0 -> 1150 bytes images/logo.png | Bin 0 -> 74722 bytes images/logo128.png | Bin 0 -> 19530 bytes images/logo144.png | Bin 0 -> 21699 bytes images/logo192.png | Bin 0 -> 31397 bytes images/logo256.png | Bin 0 -> 46658 bytes images/logo384.png | Bin 0 -> 87082 bytes images/logo72.png | Bin 0 -> 10161 bytes images/logo96.png | Bin 0 -> 13753 bytes index.html | 82 + manifest.json | 61 + nav.html | 3 + node_modules/.bin/web-push | 15 + node_modules/.bin/web-push.cmd | 17 + node_modules/.bin/web-push.ps1 | 18 + node_modules/agent-base/README.md | 145 + node_modules/agent-base/dist/src/index.d.ts | 78 + node_modules/agent-base/dist/src/index.js | 203 + node_modules/agent-base/dist/src/index.js.map | 1 + .../agent-base/dist/src/promisify.d.ts | 4 + node_modules/agent-base/dist/src/promisify.js | 18 + .../agent-base/dist/src/promisify.js.map | 1 + node_modules/agent-base/package.json | 94 + node_modules/agent-base/src/index.ts | 345 + node_modules/agent-base/src/promisify.ts | 33 + node_modules/asn1.js/.eslintrc.js | 27 + node_modules/asn1.js/LICENSE | 21 + node_modules/asn1.js/README.md | 100 + node_modules/asn1.js/lib/asn1.js | 11 + node_modules/asn1.js/lib/asn1/api.js | 57 + node_modules/asn1.js/lib/asn1/base/buffer.js | 153 + node_modules/asn1.js/lib/asn1/base/index.js | 8 + node_modules/asn1.js/lib/asn1/base/node.js | 638 + .../asn1.js/lib/asn1/base/reporter.js | 123 + .../asn1.js/lib/asn1/constants/der.js | 58 + .../asn1.js/lib/asn1/constants/index.js | 21 + node_modules/asn1.js/lib/asn1/decoders/der.js | 335 + .../asn1.js/lib/asn1/decoders/index.js | 6 + node_modules/asn1.js/lib/asn1/decoders/pem.js | 51 + node_modules/asn1.js/lib/asn1/encoders/der.js | 295 + .../asn1.js/lib/asn1/encoders/index.js | 6 + node_modules/asn1.js/lib/asn1/encoders/pem.js | 23 + node_modules/asn1.js/package.json | 63 + node_modules/bn.js/README.md | 221 + node_modules/bn.js/lib/bn.js | 3433 +++++ node_modules/bn.js/package.json | 64 + node_modules/bn.js/util/genCombMulTo.js | 65 + node_modules/bn.js/util/genCombMulTo10.js | 65 + .../buffer-equal-constant-time/.npmignore | 2 + .../buffer-equal-constant-time/.travis.yml | 4 + .../buffer-equal-constant-time/LICENSE.txt | 12 + .../buffer-equal-constant-time/README.md | 50 + .../buffer-equal-constant-time/index.js | 41 + .../buffer-equal-constant-time/package.json | 55 + .../buffer-equal-constant-time/test.js | 42 + node_modules/debug/LICENSE | 19 + node_modules/debug/README.md | 455 + node_modules/debug/package.json | 102 + node_modules/debug/src/browser.js | 269 + node_modules/debug/src/common.js | 261 + node_modules/debug/src/index.js | 10 + node_modules/debug/src/node.js | 263 + node_modules/ecdsa-sig-formatter/CODEOWNERS | 1 + node_modules/ecdsa-sig-formatter/LICENSE | 201 + node_modules/ecdsa-sig-formatter/README.md | 65 + node_modules/ecdsa-sig-formatter/package.json | 73 + .../src/ecdsa-sig-formatter.d.ts | 17 + .../src/ecdsa-sig-formatter.js | 187 + .../src/param-bytes-for-alg.js | 23 + node_modules/http_ece/README.md | 28 + node_modules/http_ece/ece.js | 522 + node_modules/http_ece/package.json | 59 + node_modules/http_ece/package.json~ | 30 + node_modules/http_ece/tmp.js~ | 36 + node_modules/https-proxy-agent/README.md | 137 + .../https-proxy-agent/dist/agent.d.ts | 30 + node_modules/https-proxy-agent/dist/agent.js | 180 + .../https-proxy-agent/dist/agent.js.map | 1 + .../https-proxy-agent/dist/index.d.ts | 23 + node_modules/https-proxy-agent/dist/index.js | 14 + .../https-proxy-agent/dist/index.js.map | 1 + .../dist/parse-proxy-response.d.ts | 7 + .../dist/parse-proxy-response.js | 66 + .../dist/parse-proxy-response.js.map | 1 + node_modules/https-proxy-agent/package.json | 86 + node_modules/inherits/LICENSE | 16 + node_modules/inherits/README.md | 42 + node_modules/inherits/inherits.js | 9 + node_modules/inherits/inherits_browser.js | 27 + node_modules/inherits/package.json | 61 + node_modules/jwa/LICENSE | 17 + node_modules/jwa/README.md | 150 + node_modules/jwa/index.js | 252 + node_modules/jwa/package.json | 69 + node_modules/jws/CHANGELOG.md | 34 + node_modules/jws/LICENSE | 17 + node_modules/jws/index.js | 22 + node_modules/jws/lib/data-stream.js | 55 + node_modules/jws/lib/sign-stream.js | 78 + node_modules/jws/lib/tostring.js | 10 + node_modules/jws/lib/verify-stream.js | 120 + node_modules/jws/package.json | 64 + node_modules/jws/readme.md | 255 + node_modules/minimalistic-assert/LICENSE | 13 + node_modules/minimalistic-assert/index.js | 11 + node_modules/minimalistic-assert/package.json | 44 + node_modules/minimalistic-assert/readme.md | 4 + node_modules/minimist/.travis.yml | 8 + node_modules/minimist/LICENSE | 18 + node_modules/minimist/example/parse.js | 2 + node_modules/minimist/index.js | 245 + node_modules/minimist/package.json | 73 + node_modules/minimist/readme.markdown | 95 + node_modules/minimist/test/all_bool.js | 32 + node_modules/minimist/test/bool.js | 178 + node_modules/minimist/test/dash.js | 31 + node_modules/minimist/test/default_bool.js | 35 + node_modules/minimist/test/dotted.js | 22 + node_modules/minimist/test/kv_short.js | 16 + node_modules/minimist/test/long.js | 31 + node_modules/minimist/test/num.js | 36 + node_modules/minimist/test/parse.js | 197 + node_modules/minimist/test/parse_modified.js | 9 + node_modules/minimist/test/proto.js | 44 + node_modules/minimist/test/short.js | 67 + node_modules/minimist/test/stop_early.js | 15 + node_modules/minimist/test/unknown.js | 102 + node_modules/minimist/test/whitespace.js | 8 + node_modules/ms/index.js | 162 + node_modules/ms/license.md | 21 + node_modules/ms/package.json | 69 + node_modules/ms/readme.md | 60 + node_modules/safe-buffer/LICENSE | 21 + node_modules/safe-buffer/README.md | 584 + node_modules/safe-buffer/index.d.ts | 187 + node_modules/safe-buffer/index.js | 65 + node_modules/safe-buffer/package.json | 78 + node_modules/safer-buffer/LICENSE | 21 + node_modules/safer-buffer/Porting-Buffer.md | 268 + node_modules/safer-buffer/Readme.md | 156 + node_modules/safer-buffer/dangerous.js | 58 + node_modules/safer-buffer/package.json | 60 + node_modules/safer-buffer/safer.js | 77 + node_modules/safer-buffer/tests.js | 406 + node_modules/urlsafe-base64/.npmignore | 6 + node_modules/urlsafe-base64/index.js | 2 + .../urlsafe-base64/lib/urlsafe-base64.js | 77 + node_modules/urlsafe-base64/package.json | 59 + node_modules/urlsafe-base64/readme.md | 84 + node_modules/web-push/LICENSE | 5 + node_modules/web-push/README.md | 562 + node_modules/web-push/package.json | 89 + node_modules/web-push/src/cli.js | 126 + .../web-push/src/encryption-helper.js | 63 + node_modules/web-push/src/index.js | 21 + node_modules/web-push/src/vapid-helper.js | 238 + .../web-push/src/web-push-constants.js | 10 + node_modules/web-push/src/web-push-error.js | 16 + node_modules/web-push/src/web-push-lib.js | 373 + package-lock.json | 153 + push.js | 31 + script/api.js | 46 + script/idb.js | 316 + script/init.js | 4 + script/jquery-2.1.1.min.js | 4 + script/main.js | 313 + script/materialize.js | 12374 ++++++++++++++++ script/materialize.min.js | 6 + script/nav.js | 45 + script/script.js | 50 + script/uint.js | 14 + service-worker.js | 92 + style/materialize.css | 9085 ++++++++++++ style/materialize.min.css | 13 + style/style.css | 249 + 177 files changed, 39789 insertions(+) create mode 100644 hosting.txt create mode 100644 images/Color Hunt Palette 212984.png create mode 100644 images/favicon.ico create mode 100644 images/logo.png create mode 100644 images/logo128.png create mode 100644 images/logo144.png create mode 100644 images/logo192.png create mode 100644 images/logo256.png create mode 100644 images/logo384.png create mode 100644 images/logo72.png create mode 100644 images/logo96.png create mode 100644 index.html create mode 100644 manifest.json create mode 100644 nav.html create mode 100644 node_modules/.bin/web-push create mode 100644 node_modules/.bin/web-push.cmd create mode 100644 node_modules/.bin/web-push.ps1 create mode 100644 node_modules/agent-base/README.md create mode 100644 node_modules/agent-base/dist/src/index.d.ts create mode 100644 node_modules/agent-base/dist/src/index.js create mode 100644 node_modules/agent-base/dist/src/index.js.map create mode 100644 node_modules/agent-base/dist/src/promisify.d.ts create mode 100644 node_modules/agent-base/dist/src/promisify.js create mode 100644 node_modules/agent-base/dist/src/promisify.js.map create mode 100644 node_modules/agent-base/package.json create mode 100644 node_modules/agent-base/src/index.ts create mode 100644 node_modules/agent-base/src/promisify.ts create mode 100644 node_modules/asn1.js/.eslintrc.js create mode 100644 node_modules/asn1.js/LICENSE create mode 100644 node_modules/asn1.js/README.md create mode 100644 node_modules/asn1.js/lib/asn1.js create mode 100644 node_modules/asn1.js/lib/asn1/api.js create mode 100644 node_modules/asn1.js/lib/asn1/base/buffer.js create mode 100644 node_modules/asn1.js/lib/asn1/base/index.js create mode 100644 node_modules/asn1.js/lib/asn1/base/node.js create mode 100644 node_modules/asn1.js/lib/asn1/base/reporter.js create mode 100644 node_modules/asn1.js/lib/asn1/constants/der.js create mode 100644 node_modules/asn1.js/lib/asn1/constants/index.js create mode 100644 node_modules/asn1.js/lib/asn1/decoders/der.js create mode 100644 node_modules/asn1.js/lib/asn1/decoders/index.js create mode 100644 node_modules/asn1.js/lib/asn1/decoders/pem.js create mode 100644 node_modules/asn1.js/lib/asn1/encoders/der.js create mode 100644 node_modules/asn1.js/lib/asn1/encoders/index.js create mode 100644 node_modules/asn1.js/lib/asn1/encoders/pem.js create mode 100644 node_modules/asn1.js/package.json create mode 100644 node_modules/bn.js/README.md create mode 100644 node_modules/bn.js/lib/bn.js create mode 100644 node_modules/bn.js/package.json create mode 100644 node_modules/bn.js/util/genCombMulTo.js create mode 100644 node_modules/bn.js/util/genCombMulTo10.js create mode 100644 node_modules/buffer-equal-constant-time/.npmignore create mode 100644 node_modules/buffer-equal-constant-time/.travis.yml create mode 100644 node_modules/buffer-equal-constant-time/LICENSE.txt create mode 100644 node_modules/buffer-equal-constant-time/README.md create mode 100644 node_modules/buffer-equal-constant-time/index.js create mode 100644 node_modules/buffer-equal-constant-time/package.json create mode 100644 node_modules/buffer-equal-constant-time/test.js create mode 100644 node_modules/debug/LICENSE create mode 100644 node_modules/debug/README.md create mode 100644 node_modules/debug/package.json create mode 100644 node_modules/debug/src/browser.js create mode 100644 node_modules/debug/src/common.js create mode 100644 node_modules/debug/src/index.js create mode 100644 node_modules/debug/src/node.js create mode 100644 node_modules/ecdsa-sig-formatter/CODEOWNERS create mode 100644 node_modules/ecdsa-sig-formatter/LICENSE create mode 100644 node_modules/ecdsa-sig-formatter/README.md create mode 100644 node_modules/ecdsa-sig-formatter/package.json create mode 100644 node_modules/ecdsa-sig-formatter/src/ecdsa-sig-formatter.d.ts create mode 100644 node_modules/ecdsa-sig-formatter/src/ecdsa-sig-formatter.js create mode 100644 node_modules/ecdsa-sig-formatter/src/param-bytes-for-alg.js create mode 100644 node_modules/http_ece/README.md create mode 100644 node_modules/http_ece/ece.js create mode 100644 node_modules/http_ece/package.json create mode 100644 node_modules/http_ece/package.json~ create mode 100644 node_modules/http_ece/tmp.js~ create mode 100644 node_modules/https-proxy-agent/README.md create mode 100644 node_modules/https-proxy-agent/dist/agent.d.ts create mode 100644 node_modules/https-proxy-agent/dist/agent.js create mode 100644 node_modules/https-proxy-agent/dist/agent.js.map create mode 100644 node_modules/https-proxy-agent/dist/index.d.ts create mode 100644 node_modules/https-proxy-agent/dist/index.js create mode 100644 node_modules/https-proxy-agent/dist/index.js.map create mode 100644 node_modules/https-proxy-agent/dist/parse-proxy-response.d.ts create mode 100644 node_modules/https-proxy-agent/dist/parse-proxy-response.js create mode 100644 node_modules/https-proxy-agent/dist/parse-proxy-response.js.map create mode 100644 node_modules/https-proxy-agent/package.json create mode 100644 node_modules/inherits/LICENSE create mode 100644 node_modules/inherits/README.md create mode 100644 node_modules/inherits/inherits.js create mode 100644 node_modules/inherits/inherits_browser.js create mode 100644 node_modules/inherits/package.json create mode 100644 node_modules/jwa/LICENSE create mode 100644 node_modules/jwa/README.md create mode 100644 node_modules/jwa/index.js create mode 100644 node_modules/jwa/package.json create mode 100644 node_modules/jws/CHANGELOG.md create mode 100644 node_modules/jws/LICENSE create mode 100644 node_modules/jws/index.js create mode 100644 node_modules/jws/lib/data-stream.js create mode 100644 node_modules/jws/lib/sign-stream.js create mode 100644 node_modules/jws/lib/tostring.js create mode 100644 node_modules/jws/lib/verify-stream.js create mode 100644 node_modules/jws/package.json create mode 100644 node_modules/jws/readme.md create mode 100644 node_modules/minimalistic-assert/LICENSE create mode 100644 node_modules/minimalistic-assert/index.js create mode 100644 node_modules/minimalistic-assert/package.json create mode 100644 node_modules/minimalistic-assert/readme.md create mode 100644 node_modules/minimist/.travis.yml create mode 100644 node_modules/minimist/LICENSE create mode 100644 node_modules/minimist/example/parse.js create mode 100644 node_modules/minimist/index.js create mode 100644 node_modules/minimist/package.json create mode 100644 node_modules/minimist/readme.markdown create mode 100644 node_modules/minimist/test/all_bool.js create mode 100644 node_modules/minimist/test/bool.js create mode 100644 node_modules/minimist/test/dash.js create mode 100644 node_modules/minimist/test/default_bool.js create mode 100644 node_modules/minimist/test/dotted.js create mode 100644 node_modules/minimist/test/kv_short.js create mode 100644 node_modules/minimist/test/long.js create mode 100644 node_modules/minimist/test/num.js create mode 100644 node_modules/minimist/test/parse.js create mode 100644 node_modules/minimist/test/parse_modified.js create mode 100644 node_modules/minimist/test/proto.js create mode 100644 node_modules/minimist/test/short.js create mode 100644 node_modules/minimist/test/stop_early.js create mode 100644 node_modules/minimist/test/unknown.js create mode 100644 node_modules/minimist/test/whitespace.js create mode 100644 node_modules/ms/index.js create mode 100644 node_modules/ms/license.md create mode 100644 node_modules/ms/package.json create mode 100644 node_modules/ms/readme.md create mode 100644 node_modules/safe-buffer/LICENSE create mode 100644 node_modules/safe-buffer/README.md create mode 100644 node_modules/safe-buffer/index.d.ts create mode 100644 node_modules/safe-buffer/index.js create mode 100644 node_modules/safe-buffer/package.json create mode 100644 node_modules/safer-buffer/LICENSE create mode 100644 node_modules/safer-buffer/Porting-Buffer.md create mode 100644 node_modules/safer-buffer/Readme.md create mode 100644 node_modules/safer-buffer/dangerous.js create mode 100644 node_modules/safer-buffer/package.json create mode 100644 node_modules/safer-buffer/safer.js create mode 100644 node_modules/safer-buffer/tests.js create mode 100644 node_modules/urlsafe-base64/.npmignore create mode 100644 node_modules/urlsafe-base64/index.js create mode 100644 node_modules/urlsafe-base64/lib/urlsafe-base64.js create mode 100644 node_modules/urlsafe-base64/package.json create mode 100644 node_modules/urlsafe-base64/readme.md create mode 100644 node_modules/web-push/LICENSE create mode 100644 node_modules/web-push/README.md create mode 100644 node_modules/web-push/package.json create mode 100644 node_modules/web-push/src/cli.js create mode 100644 node_modules/web-push/src/encryption-helper.js create mode 100644 node_modules/web-push/src/index.js create mode 100644 node_modules/web-push/src/vapid-helper.js create mode 100644 node_modules/web-push/src/web-push-constants.js create mode 100644 node_modules/web-push/src/web-push-error.js create mode 100644 node_modules/web-push/src/web-push-lib.js create mode 100644 package-lock.json create mode 100644 push.js create mode 100644 script/api.js create mode 100644 script/idb.js create mode 100644 script/init.js create mode 100644 script/jquery-2.1.1.min.js create mode 100644 script/main.js create mode 100644 script/materialize.js create mode 100644 script/materialize.min.js create mode 100644 script/nav.js create mode 100644 script/script.js create mode 100644 script/uint.js create mode 100644 service-worker.js create mode 100644 style/materialize.css create mode 100644 style/materialize.min.css create mode 100644 style/style.css diff --git a/hosting.txt b/hosting.txt new file mode 100644 index 0000000..344ccaf --- /dev/null +++ b/hosting.txt @@ -0,0 +1 @@ +bryanyehuda.github.io \ No newline at end of file diff --git a/images/Color Hunt Palette 212984.png b/images/Color Hunt Palette 212984.png new file mode 100644 index 0000000000000000000000000000000000000000..24e60e181d5bf6d9fae0d6cfa5318af9aaa896f6 GIT binary patch literal 17628 zcmeAS@N?(olHy`uVBq!ia0y~yVAW?}V4BXs1{6sy+kc;dL4m>3#WAEJ?(JRO?&YO2 zM<4#*yL(s0w$4D^M@njwucqAk{=nOaBZ}oU*CDgXVfPyoHgzn}dH4B@ZnBxayv6k? zGtHit&&{_wbGUHc^U9qudgk-vV&+ay*I)nd_bqltCKe6>1&0O(WJcW519NY0*DHU2 zXWyNDrGLKX_Rs$K>FL$4Pd|R1zTT+)y(_A6hyjiNMRydx-m$0h`_|KiwY9Z&Rlk^o zkxhl$W5i@`-&ko=`|s19pP_~FSRBA1pus8AKhMT~{omfxLF$_@TnIF);Ip~@|GGbC z>Yo>KVKd?hOV9M3UMxyzegnDUf!l$Kmwa&dATd0+B=je5<-q2_hL4wcvAJV{h(VlM zwqO@Z2tti~yi^)JY(X*#nhAS+t|^IN3!P)$=2%?Z;1G16V&)oG4Q$cXGd&M$ge+3M(dc-%73&~Hrgt~EE-0e z%cK1mEWMJ^e#~eGbF}A=SzK}mjQ0FThh#AOT>_&+GNVH>qeC*ILo%2}!|0IA=#UJS zhQx>;k~#44Tl@F(DMnc5S7wM=+^hOu{P^h?&I%jMnU=<74Iek%><+=wb9n}wPWi0P zfMpKIA^1SW%{Q)ESZ0kr1E+0%3Nv7tYgz!Doyz&9B#Olim5h&{{^4Xm%<#aqUjWX6 znN?53G7ENKPs7Kee=H1`#e_fxaJFssUJop@Z3%G)DlF@n7_g)w6QFO;#x228?i%PP z?3rWF$bcn?W&wShrXPf5IAn&nLEO3dz$sTuUB1A{u+8EtvAE$3w}k$4e+Dd5Xrs{t zO%kKg1W8fU%1t|kFH6AI0zlL1XwHHbM56^Dq^uq-03l^{<7hnvX$*|kQ;?!^v^fE7 zeT}yIAZ@nMRv)CfJKBU8Z9<@Qd`6oPqfH2uj{j&Af`}$WU-`Sc_V;)Et}>pBZGeX3 z442IOnr}xfe^>FV!-q@|3S-a4(^OX$-4lB-CovCf0nXU&s_VznRTSvULm$EZv}U0Wb!JMoXsA3^|%1>6;;Gp9v3qeDKi!xqSUU)7}Rkv93hb yn#xaKBDEKqV6*WIXHCufy{Fyf_f-EBUwAV1-`b8hJAkK_FnGH9xvXEkb_;paa5l&eb(fjf|56|=G_vg8Id4ce2BV`iR1MwyjbMnBM&y4jq$EJrkoe}UR*WxNPYT< zqx}#M&Q{V;*DyaNyqq>N}BSskpO*`os3`FOISXIA~iC5=QQt} zjl3VIW$t=4Z(>1H-aj^kY}t-tKf=^ND-pSgWp@joJ*_0~pEP#Z&qB~`$}66G^q;9D ze7k{(z9u3L3(1jARz})Ljkfdh)?s2#22J_sWB~bm9nOnKaklMd_*@n9-8IZyJHUig zi@&FVrRM=tUek1Pxg1|sRAQ4)8FgI2KWJxZ+Q-+Fx~6HGX3B3A^immp6K`fC_b>aO I|G?kYAIq1J(EtDd literal 0 HcmV?d00001 diff --git a/images/logo.png b/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e9b0af5a8e9394b98d91a4801ced6d51d85a9358 GIT binary patch literal 74722 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℘0n-UBVxYw`U{Bm%TnlG^C%F3T#M{K* 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 hY}g3@AO6=f>Ykrh5daVbbbJ5) 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ΜrHP#t#F2w3;{Y$6I!^L8S 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 I)H5Of2LKtPp8x;= literal 0 HcmV?d00001 diff --git a/images/logo72.png b/images/logo72.png new file mode 100644 index 0000000000000000000000000000000000000000..88d1d51209d7a8a54ddb3d09307c9db0bc90236b GIT binary patch literal 10161 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 literal 0 HcmV?d00001 diff --git a/images/logo96.png b/images/logo96.png new file mode 100644 index 0000000000000000000000000000000000000000..9ea4540a82f78d6216f06c23aaaacef181ae6611 GIT binary patch literal 13753 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 PKUXO$s39v5W+DFzrMV#x literal 0 HcmV?d00001 diff --git a/index.html b/index.html new file mode 100644 index 0000000..b599de5 --- /dev/null +++ b/index.html @@ -0,0 +1,82 @@ + + + + + + + + + Football Watch + + + + + + + + + + + + + + + + + + + +

+ + + +
+
+
+
+
+
+
+ + + +
+
+
+
+
Football Watch
+

The only website you need for Football Information

+
+
+
+ +
+ + + + + + + + + + + + + + + + diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..0c3a4eb --- /dev/null +++ b/manifest.json @@ -0,0 +1,61 @@ +{ + "name": "Football Watch - Watch Football Anywhere", + "short_name": "Football Watch", + "description": "Football Watch is a website that gives you all the information for you hardcore football fans", + "start_url": "/index.html", + "display": "standalone", + "background_color": "#14274e", + "theme_color": "#14274e", + "gcm_sender_id": "411668443247", + "applicationServerKey": "AAAAX9lZ8G8:APA91bGKNwyE5LiixDD8givH3iCyhB306v7h1btALDxacjfbSR9Z-8kpWi39xGDp5iZp0hg2OH9wl7Lvlpj1paIw_WDxIyiKRSQgEPQSSczypMlwNcShlp80xRXRlWh7q8EN3jumh_si", + "icons": [ + { + "src": "/images/logo72.png", + "sizes": "72x72", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "/images/logo96.png", + "sizes": "96x96", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "/images/logo128.png", + "sizes": "128x128", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "/images/logo144.png", + "sizes": "144x144", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "/images/logo192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "/images/logo256.png", + "sizes": "256x256", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "/images/logo384.png", + "sizes": "384x384", + "type": "image/png", + "purpose": "any maskable" + }, + { + "src": "/images/logo.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "any maskable" + } + ] +} \ No newline at end of file diff --git a/nav.html b/nav.html new file mode 100644 index 0000000..d8616b9 --- /dev/null +++ b/nav.html @@ -0,0 +1,3 @@ +
  • Teams
  • +
  • Standings
  • +
  • Favorite Teams
  • \ No newline at end of file diff --git a/node_modules/.bin/web-push b/node_modules/.bin/web-push new file mode 100644 index 0000000..8228fa2 --- /dev/null +++ b/node_modules/.bin/web-push @@ -0,0 +1,15 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;; +esac + +if [ -x "$basedir/node" ]; then + "$basedir/node" "$basedir/../web-push/src/cli.js" "$@" + ret=$? +else + node "$basedir/../web-push/src/cli.js" "$@" + ret=$? +fi +exit $ret diff --git a/node_modules/.bin/web-push.cmd b/node_modules/.bin/web-push.cmd new file mode 100644 index 0000000..1796427 --- /dev/null +++ b/node_modules/.bin/web-push.cmd @@ -0,0 +1,17 @@ +@ECHO off +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +"%_prog%" "%dp0%\..\web-push\src\cli.js" %* +ENDLOCAL +EXIT /b %errorlevel% +:find_dp0 +SET dp0=%~dp0 +EXIT /b diff --git a/node_modules/.bin/web-push.ps1 b/node_modules/.bin/web-push.ps1 new file mode 100644 index 0000000..5d8774a --- /dev/null +++ b/node_modules/.bin/web-push.ps1 @@ -0,0 +1,18 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + & "$basedir/node$exe" "$basedir/../web-push/src/cli.js" $args + $ret=$LASTEXITCODE +} else { + & "node$exe" "$basedir/../web-push/src/cli.js" $args + $ret=$LASTEXITCODE +} +exit $ret diff --git a/node_modules/agent-base/README.md b/node_modules/agent-base/README.md new file mode 100644 index 0000000..256f1f3 --- /dev/null +++ b/node_modules/agent-base/README.md @@ -0,0 +1,145 @@ +agent-base +========== +### Turn a function into an [`http.Agent`][http.Agent] instance +[![Build Status](https://github.com/TooTallNate/node-agent-base/workflows/Node%20CI/badge.svg)](https://github.com/TooTallNate/node-agent-base/actions?workflow=Node+CI) + +This module provides an `http.Agent` generator. That is, you pass it an async +callback function, and it returns a new `http.Agent` instance that will invoke the +given callback function when sending outbound HTTP requests. + +#### Some subclasses: + +Here's some more interesting uses of `agent-base`. +Send a pull request to list yours! + + * [`http-proxy-agent`][http-proxy-agent]: An HTTP(s) proxy `http.Agent` implementation for HTTP endpoints + * [`https-proxy-agent`][https-proxy-agent]: An HTTP(s) proxy `http.Agent` implementation for HTTPS endpoints + * [`pac-proxy-agent`][pac-proxy-agent]: A PAC file proxy `http.Agent` implementation for HTTP and HTTPS + * [`socks-proxy-agent`][socks-proxy-agent]: A SOCKS proxy `http.Agent` implementation for HTTP and HTTPS + + +Installation +------------ + +Install with `npm`: + +``` bash +$ npm install agent-base +``` + + +Example +------- + +Here's a minimal example that creates a new `net.Socket` connection to the server +for every HTTP request (i.e. the equivalent of `agent: false` option): + +```js +var net = require('net'); +var tls = require('tls'); +var url = require('url'); +var http = require('http'); +var agent = require('agent-base'); + +var endpoint = 'http://nodejs.org/api/'; +var parsed = url.parse(endpoint); + +// This is the important part! +parsed.agent = agent(function (req, opts) { + var socket; + // `secureEndpoint` is true when using the https module + if (opts.secureEndpoint) { + socket = tls.connect(opts); + } else { + socket = net.connect(opts); + } + return socket; +}); + +// Everything else works just like normal... +http.get(parsed, function (res) { + console.log('"response" event!', res.headers); + res.pipe(process.stdout); +}); +``` + +Returning a Promise or using an `async` function is also supported: + +```js +agent(async function (req, opts) { + await sleep(1000); + // etc… +}); +``` + +Return another `http.Agent` instance to "pass through" the responsibility +for that HTTP request to that agent: + +```js +agent(function (req, opts) { + return opts.secureEndpoint ? https.globalAgent : http.globalAgent; +}); +``` + + +API +--- + +## Agent(Function callback[, Object options]) → [http.Agent][] + +Creates a base `http.Agent` that will execute the callback function `callback` +for every HTTP request that it is used as the `agent` for. The callback function +is responsible for creating a `stream.Duplex` instance of some kind that will be +used as the underlying socket in the HTTP request. + +The `options` object accepts the following properties: + + * `timeout` - Number - Timeout for the `callback()` function in milliseconds. Defaults to Infinity (optional). + +The callback function should have the following signature: + +### callback(http.ClientRequest req, Object options, Function cb) → undefined + +The ClientRequest `req` can be accessed to read request headers and +and the path, etc. The `options` object contains the options passed +to the `http.request()`/`https.request()` function call, and is formatted +to be directly passed to `net.connect()`/`tls.connect()`, or however +else you want a Socket to be created. Pass the created socket to +the callback function `cb` once created, and the HTTP request will +continue to proceed. + +If the `https` module is used to invoke the HTTP request, then the +`secureEndpoint` property on `options` _will be set to `true`_. + + +License +------- + +(The MIT License) + +Copyright (c) 2013 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. + +[http-proxy-agent]: https://github.com/TooTallNate/node-http-proxy-agent +[https-proxy-agent]: https://github.com/TooTallNate/node-https-proxy-agent +[pac-proxy-agent]: https://github.com/TooTallNate/node-pac-proxy-agent +[socks-proxy-agent]: https://github.com/TooTallNate/node-socks-proxy-agent +[http.Agent]: https://nodejs.org/api/http.html#http_class_http_agent diff --git a/node_modules/agent-base/dist/src/index.d.ts b/node_modules/agent-base/dist/src/index.d.ts new file mode 100644 index 0000000..bc4ab74 --- /dev/null +++ b/node_modules/agent-base/dist/src/index.d.ts @@ -0,0 +1,78 @@ +/// +import net from 'net'; +import http from 'http'; +import https from 'https'; +import { Duplex } from 'stream'; +import { EventEmitter } from 'events'; +declare function createAgent(opts?: createAgent.AgentOptions): createAgent.Agent; +declare function createAgent(callback: createAgent.AgentCallback, opts?: createAgent.AgentOptions): createAgent.Agent; +declare namespace createAgent { + interface ClientRequest extends http.ClientRequest { + _last?: boolean; + _hadError?: boolean; + method: string; + } + interface AgentRequestOptions { + host?: string; + path?: string; + port: number; + } + interface HttpRequestOptions extends AgentRequestOptions, Omit { + secureEndpoint: false; + } + interface HttpsRequestOptions extends AgentRequestOptions, Omit { + secureEndpoint: true; + } + type RequestOptions = HttpRequestOptions | HttpsRequestOptions; + type AgentLike = Pick | http.Agent; + type AgentCallbackReturn = Duplex | AgentLike; + type AgentCallbackCallback = (err?: Error | null, socket?: createAgent.AgentCallbackReturn) => void; + type AgentCallbackPromise = (req: createAgent.ClientRequest, opts: createAgent.RequestOptions) => createAgent.AgentCallbackReturn | Promise; + type AgentCallback = typeof Agent.prototype.callback; + type AgentOptions = { + timeout?: number; + }; + /** + * Base `http.Agent` implementation. + * No pooling/keep-alive is implemented by default. + * + * @param {Function} callback + * @api public + */ + class Agent extends EventEmitter { + timeout: number | null; + maxFreeSockets: number; + maxTotalSockets: number; + maxSockets: number; + sockets: { + [key: string]: net.Socket[]; + }; + freeSockets: { + [key: string]: net.Socket[]; + }; + requests: { + [key: string]: http.IncomingMessage[]; + }; + options: https.AgentOptions; + private promisifiedCallback?; + private explicitDefaultPort?; + private explicitProtocol?; + constructor(callback?: createAgent.AgentCallback | createAgent.AgentOptions, _opts?: createAgent.AgentOptions); + get defaultPort(): number; + set defaultPort(v: number); + get protocol(): string; + set protocol(v: string); + callback(req: createAgent.ClientRequest, opts: createAgent.RequestOptions, fn: createAgent.AgentCallbackCallback): void; + callback(req: createAgent.ClientRequest, opts: createAgent.RequestOptions): createAgent.AgentCallbackReturn | Promise; + /** + * Called by node-core's "_http_client.js" module when creating + * a new HTTP request with this Agent instance. + * + * @api public + */ + addRequest(req: ClientRequest, _opts: RequestOptions): void; + freeSocket(socket: net.Socket, opts: AgentOptions): void; + destroy(): void; + } +} +export = createAgent; diff --git a/node_modules/agent-base/dist/src/index.js b/node_modules/agent-base/dist/src/index.js new file mode 100644 index 0000000..bfd9e22 --- /dev/null +++ b/node_modules/agent-base/dist/src/index.js @@ -0,0 +1,203 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +const events_1 = require("events"); +const debug_1 = __importDefault(require("debug")); +const promisify_1 = __importDefault(require("./promisify")); +const debug = debug_1.default('agent-base'); +function isAgent(v) { + return Boolean(v) && typeof v.addRequest === 'function'; +} +function isSecureEndpoint() { + const { stack } = new Error(); + if (typeof stack !== 'string') + return false; + return stack.split('\n').some(l => l.indexOf('(https.js:') !== -1 || l.indexOf('node:https:') !== -1); +} +function createAgent(callback, opts) { + return new createAgent.Agent(callback, opts); +} +(function (createAgent) { + /** + * Base `http.Agent` implementation. + * No pooling/keep-alive is implemented by default. + * + * @param {Function} callback + * @api public + */ + class Agent extends events_1.EventEmitter { + constructor(callback, _opts) { + super(); + let opts = _opts; + if (typeof callback === 'function') { + this.callback = callback; + } + else if (callback) { + opts = callback; + } + // Timeout for the socket to be returned from the callback + this.timeout = null; + if (opts && typeof opts.timeout === 'number') { + this.timeout = opts.timeout; + } + // These aren't actually used by `agent-base`, but are required + // for the TypeScript definition files in `@types/node` :/ + this.maxFreeSockets = 1; + this.maxSockets = 1; + this.maxTotalSockets = Infinity; + this.sockets = {}; + this.freeSockets = {}; + this.requests = {}; + this.options = {}; + } + get defaultPort() { + if (typeof this.explicitDefaultPort === 'number') { + return this.explicitDefaultPort; + } + return isSecureEndpoint() ? 443 : 80; + } + set defaultPort(v) { + this.explicitDefaultPort = v; + } + get protocol() { + if (typeof this.explicitProtocol === 'string') { + return this.explicitProtocol; + } + return isSecureEndpoint() ? 'https:' : 'http:'; + } + set protocol(v) { + this.explicitProtocol = v; + } + callback(req, opts, fn) { + throw new Error('"agent-base" has no default implementation, you must subclass and override `callback()`'); + } + /** + * Called by node-core's "_http_client.js" module when creating + * a new HTTP request with this Agent instance. + * + * @api public + */ + addRequest(req, _opts) { + const opts = Object.assign({}, _opts); + if (typeof opts.secureEndpoint !== 'boolean') { + opts.secureEndpoint = isSecureEndpoint(); + } + if (opts.host == null) { + opts.host = 'localhost'; + } + if (opts.port == null) { + opts.port = opts.secureEndpoint ? 443 : 80; + } + if (opts.protocol == null) { + opts.protocol = opts.secureEndpoint ? 'https:' : 'http:'; + } + if (opts.host && opts.path) { + // If both a `host` and `path` are specified then it's most + // likely the result of a `url.parse()` call... we need to + // remove the `path` portion so that `net.connect()` doesn't + // attempt to open that as a unix socket file. + delete opts.path; + } + delete opts.agent; + delete opts.hostname; + delete opts._defaultAgent; + delete opts.defaultPort; + delete opts.createConnection; + // Hint to use "Connection: close" + // XXX: non-documented `http` module API :( + req._last = true; + req.shouldKeepAlive = false; + let timedOut = false; + let timeoutId = null; + const timeoutMs = opts.timeout || this.timeout; + const onerror = (err) => { + if (req._hadError) + return; + req.emit('error', err); + // For Safety. Some additional errors might fire later on + // and we need to make sure we don't double-fire the error event. + req._hadError = true; + }; + const ontimeout = () => { + timeoutId = null; + timedOut = true; + const err = new Error(`A "socket" was not created for HTTP request before ${timeoutMs}ms`); + err.code = 'ETIMEOUT'; + onerror(err); + }; + const callbackError = (err) => { + if (timedOut) + return; + if (timeoutId !== null) { + clearTimeout(timeoutId); + timeoutId = null; + } + onerror(err); + }; + const onsocket = (socket) => { + if (timedOut) + return; + if (timeoutId != null) { + clearTimeout(timeoutId); + timeoutId = null; + } + if (isAgent(socket)) { + // `socket` is actually an `http.Agent` instance, so + // relinquish responsibility for this `req` to the Agent + // from here on + debug('Callback returned another Agent instance %o', socket.constructor.name); + socket.addRequest(req, opts); + return; + } + if (socket) { + socket.once('free', () => { + this.freeSocket(socket, opts); + }); + req.onSocket(socket); + return; + } + const err = new Error(`no Duplex stream was returned to agent-base for \`${req.method} ${req.path}\``); + onerror(err); + }; + if (typeof this.callback !== 'function') { + onerror(new Error('`callback` is not defined')); + return; + } + if (!this.promisifiedCallback) { + if (this.callback.length >= 3) { + debug('Converting legacy callback function to promise'); + this.promisifiedCallback = promisify_1.default(this.callback); + } + else { + this.promisifiedCallback = this.callback; + } + } + if (typeof timeoutMs === 'number' && timeoutMs > 0) { + timeoutId = setTimeout(ontimeout, timeoutMs); + } + if ('port' in opts && typeof opts.port !== 'number') { + opts.port = Number(opts.port); + } + try { + debug('Resolving socket for %o request: %o', opts.protocol, `${req.method} ${req.path}`); + Promise.resolve(this.promisifiedCallback(req, opts)).then(onsocket, callbackError); + } + catch (err) { + Promise.reject(err).catch(callbackError); + } + } + freeSocket(socket, opts) { + debug('Freeing socket %o %o', socket.constructor.name, opts); + socket.destroy(); + } + destroy() { + debug('Destroying agent %o', this.constructor.name); + } + } + createAgent.Agent = Agent; + // So that `instanceof` works correctly + createAgent.prototype = createAgent.Agent.prototype; +})(createAgent || (createAgent = {})); +module.exports = createAgent; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/node_modules/agent-base/dist/src/index.js.map b/node_modules/agent-base/dist/src/index.js.map new file mode 100644 index 0000000..bd118ab --- /dev/null +++ b/node_modules/agent-base/dist/src/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/node_modules/agent-base/dist/src/promisify.d.ts b/node_modules/agent-base/dist/src/promisify.d.ts new file mode 100644 index 0000000..0268869 --- /dev/null +++ b/node_modules/agent-base/dist/src/promisify.d.ts @@ -0,0 +1,4 @@ +import { ClientRequest, RequestOptions, AgentCallbackCallback, AgentCallbackPromise } from './index'; +declare type LegacyCallback = (req: ClientRequest, opts: RequestOptions, fn: AgentCallbackCallback) => void; +export default function promisify(fn: LegacyCallback): AgentCallbackPromise; +export {}; diff --git a/node_modules/agent-base/dist/src/promisify.js b/node_modules/agent-base/dist/src/promisify.js new file mode 100644 index 0000000..b2f6132 --- /dev/null +++ b/node_modules/agent-base/dist/src/promisify.js @@ -0,0 +1,18 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function promisify(fn) { + return function (req, opts) { + return new Promise((resolve, reject) => { + fn.call(this, req, opts, (err, rtn) => { + if (err) { + reject(err); + } + else { + resolve(rtn); + } + }); + }); + }; +} +exports.default = promisify; +//# sourceMappingURL=promisify.js.map \ No newline at end of file diff --git a/node_modules/agent-base/dist/src/promisify.js.map b/node_modules/agent-base/dist/src/promisify.js.map new file mode 100644 index 0000000..4bff9bf --- /dev/null +++ b/node_modules/agent-base/dist/src/promisify.js.map @@ -0,0 +1 @@ +{"version":3,"file":"promisify.js","sourceRoot":"","sources":["../../src/promisify.ts"],"names":[],"mappings":";;AAeA,SAAwB,SAAS,CAAC,EAAkB;IACnD,OAAO,UAAsB,GAAkB,EAAE,IAAoB;QACpE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACtC,EAAE,CAAC,IAAI,CACN,IAAI,EACJ,GAAG,EACH,IAAI,EACJ,CAAC,GAA6B,EAAE,GAAyB,EAAE,EAAE;gBAC5D,IAAI,GAAG,EAAE;oBACR,MAAM,CAAC,GAAG,CAAC,CAAC;iBACZ;qBAAM;oBACN,OAAO,CAAC,GAAG,CAAC,CAAC;iBACb;YACF,CAAC,CACD,CAAC;QACH,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC;AACH,CAAC;AAjBD,4BAiBC"} \ No newline at end of file diff --git a/node_modules/agent-base/package.json b/node_modules/agent-base/package.json new file mode 100644 index 0000000..4221144 --- /dev/null +++ b/node_modules/agent-base/package.json @@ -0,0 +1,94 @@ +{ + "_from": "agent-base@6", + "_id": "agent-base@6.0.2", + "_inBundle": false, + "_integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "_location": "/agent-base", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "agent-base@6", + "name": "agent-base", + "escapedName": "agent-base", + "rawSpec": "6", + "saveSpec": null, + "fetchSpec": "6" + }, + "_requiredBy": [ + "/https-proxy-agent" + ], + "_resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "_shasum": "49fff58577cfee3f37176feab4c22e00f86d7f77", + "_spec": "agent-base@6", + "_where": "D:\\Users\\user\\Documents\\Portofolio\\Github\\WebsiteFootballPWA\\node_modules\\https-proxy-agent", + "author": { + "name": "Nathan Rajlich", + "email": "nathan@tootallnate.net", + "url": "http://n8.io/" + }, + "bugs": { + "url": "https://github.com/TooTallNate/node-agent-base/issues" + }, + "bundleDependencies": false, + "dependencies": { + "debug": "4" + }, + "deprecated": false, + "description": "Turn a function into an `http.Agent` instance", + "devDependencies": { + "@types/debug": "4", + "@types/mocha": "^5.2.7", + "@types/node": "^14.0.20", + "@types/semver": "^7.1.0", + "@types/ws": "^6.0.3", + "@typescript-eslint/eslint-plugin": "1.6.0", + "@typescript-eslint/parser": "1.1.0", + "async-listen": "^1.2.0", + "cpy-cli": "^2.0.0", + "eslint": "5.16.0", + "eslint-config-airbnb": "17.1.0", + "eslint-config-prettier": "4.1.0", + "eslint-import-resolver-typescript": "1.1.1", + "eslint-plugin-import": "2.16.0", + "eslint-plugin-jsx-a11y": "6.2.1", + "eslint-plugin-react": "7.12.4", + "mocha": "^6.2.0", + "rimraf": "^3.0.0", + "semver": "^7.1.2", + "typescript": "^3.5.3", + "ws": "^3.0.0" + }, + "engines": { + "node": ">= 6.0.0" + }, + "files": [ + "dist/src", + "src" + ], + "homepage": "https://github.com/TooTallNate/node-agent-base#readme", + "keywords": [ + "http", + "agent", + "base", + "barebones", + "https" + ], + "license": "MIT", + "main": "dist/src/index", + "name": "agent-base", + "repository": { + "type": "git", + "url": "git://github.com/TooTallNate/node-agent-base.git" + }, + "scripts": { + "build": "tsc", + "postbuild": "cpy --parents src test '!**/*.ts' dist", + "prebuild": "rimraf dist", + "prepublishOnly": "npm run build", + "test": "mocha --reporter spec dist/test/*.js", + "test-lint": "eslint src --ext .js,.ts" + }, + "typings": "dist/src/index", + "version": "6.0.2" +} diff --git a/node_modules/agent-base/src/index.ts b/node_modules/agent-base/src/index.ts new file mode 100644 index 0000000..a47ccd4 --- /dev/null +++ b/node_modules/agent-base/src/index.ts @@ -0,0 +1,345 @@ +import net from 'net'; +import http from 'http'; +import https from 'https'; +import { Duplex } from 'stream'; +import { EventEmitter } from 'events'; +import createDebug from 'debug'; +import promisify from './promisify'; + +const debug = createDebug('agent-base'); + +function isAgent(v: any): v is createAgent.AgentLike { + return Boolean(v) && typeof v.addRequest === 'function'; +} + +function isSecureEndpoint(): boolean { + const { stack } = new Error(); + if (typeof stack !== 'string') return false; + return stack.split('\n').some(l => l.indexOf('(https.js:') !== -1 || l.indexOf('node:https:') !== -1); +} + +function createAgent(opts?: createAgent.AgentOptions): createAgent.Agent; +function createAgent( + callback: createAgent.AgentCallback, + opts?: createAgent.AgentOptions +): createAgent.Agent; +function createAgent( + callback?: createAgent.AgentCallback | createAgent.AgentOptions, + opts?: createAgent.AgentOptions +) { + return new createAgent.Agent(callback, opts); +} + +namespace createAgent { + export interface ClientRequest extends http.ClientRequest { + _last?: boolean; + _hadError?: boolean; + method: string; + } + + export interface AgentRequestOptions { + host?: string; + path?: string; + // `port` on `http.RequestOptions` can be a string or undefined, + // but `net.TcpNetConnectOpts` expects only a number + port: number; + } + + export interface HttpRequestOptions + extends AgentRequestOptions, + Omit { + secureEndpoint: false; + } + + export interface HttpsRequestOptions + extends AgentRequestOptions, + Omit { + secureEndpoint: true; + } + + export type RequestOptions = HttpRequestOptions | HttpsRequestOptions; + + export type AgentLike = Pick | http.Agent; + + export type AgentCallbackReturn = Duplex | AgentLike; + + export type AgentCallbackCallback = ( + err?: Error | null, + socket?: createAgent.AgentCallbackReturn + ) => void; + + export type AgentCallbackPromise = ( + req: createAgent.ClientRequest, + opts: createAgent.RequestOptions + ) => + | createAgent.AgentCallbackReturn + | Promise; + + export type AgentCallback = typeof Agent.prototype.callback; + + export type AgentOptions = { + timeout?: number; + }; + + /** + * Base `http.Agent` implementation. + * No pooling/keep-alive is implemented by default. + * + * @param {Function} callback + * @api public + */ + export class Agent extends EventEmitter { + public timeout: number | null; + public maxFreeSockets: number; + public maxTotalSockets: number; + public maxSockets: number; + public sockets: { + [key: string]: net.Socket[]; + }; + public freeSockets: { + [key: string]: net.Socket[]; + }; + public requests: { + [key: string]: http.IncomingMessage[]; + }; + public options: https.AgentOptions; + private promisifiedCallback?: createAgent.AgentCallbackPromise; + private explicitDefaultPort?: number; + private explicitProtocol?: string; + + constructor( + callback?: createAgent.AgentCallback | createAgent.AgentOptions, + _opts?: createAgent.AgentOptions + ) { + super(); + + let opts = _opts; + if (typeof callback === 'function') { + this.callback = callback; + } else if (callback) { + opts = callback; + } + + // Timeout for the socket to be returned from the callback + this.timeout = null; + if (opts && typeof opts.timeout === 'number') { + this.timeout = opts.timeout; + } + + // These aren't actually used by `agent-base`, but are required + // for the TypeScript definition files in `@types/node` :/ + this.maxFreeSockets = 1; + this.maxSockets = 1; + this.maxTotalSockets = Infinity; + this.sockets = {}; + this.freeSockets = {}; + this.requests = {}; + this.options = {}; + } + + get defaultPort(): number { + if (typeof this.explicitDefaultPort === 'number') { + return this.explicitDefaultPort; + } + return isSecureEndpoint() ? 443 : 80; + } + + set defaultPort(v: number) { + this.explicitDefaultPort = v; + } + + get protocol(): string { + if (typeof this.explicitProtocol === 'string') { + return this.explicitProtocol; + } + return isSecureEndpoint() ? 'https:' : 'http:'; + } + + set protocol(v: string) { + this.explicitProtocol = v; + } + + callback( + req: createAgent.ClientRequest, + opts: createAgent.RequestOptions, + fn: createAgent.AgentCallbackCallback + ): void; + callback( + req: createAgent.ClientRequest, + opts: createAgent.RequestOptions + ): + | createAgent.AgentCallbackReturn + | Promise; + callback( + req: createAgent.ClientRequest, + opts: createAgent.AgentOptions, + fn?: createAgent.AgentCallbackCallback + ): + | createAgent.AgentCallbackReturn + | Promise + | void { + throw new Error( + '"agent-base" has no default implementation, you must subclass and override `callback()`' + ); + } + + /** + * Called by node-core's "_http_client.js" module when creating + * a new HTTP request with this Agent instance. + * + * @api public + */ + addRequest(req: ClientRequest, _opts: RequestOptions): void { + const opts: RequestOptions = { ..._opts }; + + if (typeof opts.secureEndpoint !== 'boolean') { + opts.secureEndpoint = isSecureEndpoint(); + } + + if (opts.host == null) { + opts.host = 'localhost'; + } + + if (opts.port == null) { + opts.port = opts.secureEndpoint ? 443 : 80; + } + + if (opts.protocol == null) { + opts.protocol = opts.secureEndpoint ? 'https:' : 'http:'; + } + + if (opts.host && opts.path) { + // If both a `host` and `path` are specified then it's most + // likely the result of a `url.parse()` call... we need to + // remove the `path` portion so that `net.connect()` doesn't + // attempt to open that as a unix socket file. + delete opts.path; + } + + delete opts.agent; + delete opts.hostname; + delete opts._defaultAgent; + delete opts.defaultPort; + delete opts.createConnection; + + // Hint to use "Connection: close" + // XXX: non-documented `http` module API :( + req._last = true; + req.shouldKeepAlive = false; + + let timedOut = false; + let timeoutId: ReturnType | null = null; + const timeoutMs = opts.timeout || this.timeout; + + const onerror = (err: NodeJS.ErrnoException) => { + if (req._hadError) return; + req.emit('error', err); + // For Safety. Some additional errors might fire later on + // and we need to make sure we don't double-fire the error event. + req._hadError = true; + }; + + const ontimeout = () => { + timeoutId = null; + timedOut = true; + const err: NodeJS.ErrnoException = new Error( + `A "socket" was not created for HTTP request before ${timeoutMs}ms` + ); + err.code = 'ETIMEOUT'; + onerror(err); + }; + + const callbackError = (err: NodeJS.ErrnoException) => { + if (timedOut) return; + if (timeoutId !== null) { + clearTimeout(timeoutId); + timeoutId = null; + } + onerror(err); + }; + + const onsocket = (socket: AgentCallbackReturn) => { + if (timedOut) return; + if (timeoutId != null) { + clearTimeout(timeoutId); + timeoutId = null; + } + + if (isAgent(socket)) { + // `socket` is actually an `http.Agent` instance, so + // relinquish responsibility for this `req` to the Agent + // from here on + debug( + 'Callback returned another Agent instance %o', + socket.constructor.name + ); + (socket as createAgent.Agent).addRequest(req, opts); + return; + } + + if (socket) { + socket.once('free', () => { + this.freeSocket(socket as net.Socket, opts); + }); + req.onSocket(socket as net.Socket); + return; + } + + const err = new Error( + `no Duplex stream was returned to agent-base for \`${req.method} ${req.path}\`` + ); + onerror(err); + }; + + if (typeof this.callback !== 'function') { + onerror(new Error('`callback` is not defined')); + return; + } + + if (!this.promisifiedCallback) { + if (this.callback.length >= 3) { + debug('Converting legacy callback function to promise'); + this.promisifiedCallback = promisify(this.callback); + } else { + this.promisifiedCallback = this.callback; + } + } + + if (typeof timeoutMs === 'number' && timeoutMs > 0) { + timeoutId = setTimeout(ontimeout, timeoutMs); + } + + if ('port' in opts && typeof opts.port !== 'number') { + opts.port = Number(opts.port); + } + + try { + debug( + 'Resolving socket for %o request: %o', + opts.protocol, + `${req.method} ${req.path}` + ); + Promise.resolve(this.promisifiedCallback(req, opts)).then( + onsocket, + callbackError + ); + } catch (err) { + Promise.reject(err).catch(callbackError); + } + } + + freeSocket(socket: net.Socket, opts: AgentOptions) { + debug('Freeing socket %o %o', socket.constructor.name, opts); + socket.destroy(); + } + + destroy() { + debug('Destroying agent %o', this.constructor.name); + } + } + + // So that `instanceof` works correctly + createAgent.prototype = createAgent.Agent.prototype; +} + +export = createAgent; diff --git a/node_modules/agent-base/src/promisify.ts b/node_modules/agent-base/src/promisify.ts new file mode 100644 index 0000000..60cc662 --- /dev/null +++ b/node_modules/agent-base/src/promisify.ts @@ -0,0 +1,33 @@ +import { + Agent, + ClientRequest, + RequestOptions, + AgentCallbackCallback, + AgentCallbackPromise, + AgentCallbackReturn +} from './index'; + +type LegacyCallback = ( + req: ClientRequest, + opts: RequestOptions, + fn: AgentCallbackCallback +) => void; + +export default function promisify(fn: LegacyCallback): AgentCallbackPromise { + return function(this: Agent, req: ClientRequest, opts: RequestOptions) { + return new Promise((resolve, reject) => { + fn.call( + this, + req, + opts, + (err: Error | null | undefined, rtn?: AgentCallbackReturn) => { + if (err) { + reject(err); + } else { + resolve(rtn); + } + } + ); + }); + }; +} diff --git a/node_modules/asn1.js/.eslintrc.js b/node_modules/asn1.js/.eslintrc.js new file mode 100644 index 0000000..6b5dc44 --- /dev/null +++ b/node_modules/asn1.js/.eslintrc.js @@ -0,0 +1,27 @@ +module.exports = { + 'env': { + 'browser': false, + 'commonjs': true, + 'es6': true, + 'node': true + }, + 'extends': 'eslint:recommended', + 'rules': { + 'indent': [ + 'error', + 2 + ], + 'linebreak-style': [ + 'error', + 'unix' + ], + 'quotes': [ + 'error', + 'single' + ], + 'semi': [ + 'error', + 'always' + ] + } +}; diff --git a/node_modules/asn1.js/LICENSE b/node_modules/asn1.js/LICENSE new file mode 100644 index 0000000..caaf4f2 --- /dev/null +++ b/node_modules/asn1.js/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Fedor Indutny + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/asn1.js/README.md b/node_modules/asn1.js/README.md new file mode 100644 index 0000000..9f04af7 --- /dev/null +++ b/node_modules/asn1.js/README.md @@ -0,0 +1,100 @@ +# ASN1.js + +ASN.1 DER Encoder/Decoder and DSL. + +## Example + +Define model: + +```javascript +var asn = require('asn1.js'); + +var Human = asn.define('Human', function() { + this.seq().obj( + this.key('firstName').octstr(), + this.key('lastName').octstr(), + this.key('age').int(), + this.key('gender').enum({ 0: 'male', 1: 'female' }), + this.key('bio').seqof(Bio) + ); +}); + +var Bio = asn.define('Bio', function() { + this.seq().obj( + this.key('time').gentime(), + this.key('description').octstr() + ); +}); +``` + +Encode data: + +```javascript +var output = Human.encode({ + firstName: 'Thomas', + lastName: 'Anderson', + age: 28, + gender: 'male', + bio: [ + { + time: +new Date('31 March 1999'), + description: 'freedom of mind' + } + ] +}, 'der'); +``` + +Decode data: + +```javascript +var human = Human.decode(output, 'der'); +console.log(human); +/* +{ firstName: , + lastName: , + age: 28, + gender: 'male', + bio: + [ { time: 922820400000, + description: } ] } +*/ +``` + +### Partial decode + +Its possible to parse data without stopping on first error. In order to do it, +you should call: + +```javascript +var human = Human.decode(output, 'der', { partial: true }); +console.log(human); +/* +{ result: { ... }, + errors: [ ... ] } +*/ +``` + +#### LICENSE + +This software is licensed under the MIT License. + +Copyright Fedor Indutny, 2017. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the +following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/asn1.js/lib/asn1.js b/node_modules/asn1.js/lib/asn1.js new file mode 100644 index 0000000..c7d70b8 --- /dev/null +++ b/node_modules/asn1.js/lib/asn1.js @@ -0,0 +1,11 @@ +'use strict'; + +const asn1 = exports; + +asn1.bignum = require('bn.js'); + +asn1.define = require('./asn1/api').define; +asn1.base = require('./asn1/base'); +asn1.constants = require('./asn1/constants'); +asn1.decoders = require('./asn1/decoders'); +asn1.encoders = require('./asn1/encoders'); diff --git a/node_modules/asn1.js/lib/asn1/api.js b/node_modules/asn1.js/lib/asn1/api.js new file mode 100644 index 0000000..61e3eb2 --- /dev/null +++ b/node_modules/asn1.js/lib/asn1/api.js @@ -0,0 +1,57 @@ +'use strict'; + +const encoders = require('./encoders'); +const decoders = require('./decoders'); +const inherits = require('inherits'); + +const api = exports; + +api.define = function define(name, body) { + return new Entity(name, body); +}; + +function Entity(name, body) { + this.name = name; + this.body = body; + + this.decoders = {}; + this.encoders = {}; +} + +Entity.prototype._createNamed = function createNamed(Base) { + const name = this.name; + + function Generated(entity) { + this._initNamed(entity, name); + } + inherits(Generated, Base); + Generated.prototype._initNamed = function _initNamed(entity, name) { + Base.call(this, entity, name); + }; + + return new Generated(this); +}; + +Entity.prototype._getDecoder = function _getDecoder(enc) { + enc = enc || 'der'; + // Lazily create decoder + if (!this.decoders.hasOwnProperty(enc)) + this.decoders[enc] = this._createNamed(decoders[enc]); + return this.decoders[enc]; +}; + +Entity.prototype.decode = function decode(data, enc, options) { + return this._getDecoder(enc).decode(data, options); +}; + +Entity.prototype._getEncoder = function _getEncoder(enc) { + enc = enc || 'der'; + // Lazily create encoder + if (!this.encoders.hasOwnProperty(enc)) + this.encoders[enc] = this._createNamed(encoders[enc]); + return this.encoders[enc]; +}; + +Entity.prototype.encode = function encode(data, enc, /* internal */ reporter) { + return this._getEncoder(enc).encode(data, reporter); +}; diff --git a/node_modules/asn1.js/lib/asn1/base/buffer.js b/node_modules/asn1.js/lib/asn1/base/buffer.js new file mode 100644 index 0000000..bb5bc06 --- /dev/null +++ b/node_modules/asn1.js/lib/asn1/base/buffer.js @@ -0,0 +1,153 @@ +'use strict'; + +const inherits = require('inherits'); +const Reporter = require('../base/reporter').Reporter; +const Buffer = require('safer-buffer').Buffer; + +function DecoderBuffer(base, options) { + Reporter.call(this, options); + if (!Buffer.isBuffer(base)) { + this.error('Input not Buffer'); + return; + } + + this.base = base; + this.offset = 0; + this.length = base.length; +} +inherits(DecoderBuffer, Reporter); +exports.DecoderBuffer = DecoderBuffer; + +DecoderBuffer.isDecoderBuffer = function isDecoderBuffer(data) { + if (data instanceof DecoderBuffer) { + return true; + } + + // Or accept compatible API + const isCompatible = typeof data === 'object' && + Buffer.isBuffer(data.base) && + data.constructor.name === 'DecoderBuffer' && + typeof data.offset === 'number' && + typeof data.length === 'number' && + typeof data.save === 'function' && + typeof data.restore === 'function' && + typeof data.isEmpty === 'function' && + typeof data.readUInt8 === 'function' && + typeof data.skip === 'function' && + typeof data.raw === 'function'; + + return isCompatible; +}; + +DecoderBuffer.prototype.save = function save() { + return { offset: this.offset, reporter: Reporter.prototype.save.call(this) }; +}; + +DecoderBuffer.prototype.restore = function restore(save) { + // Return skipped data + const res = new DecoderBuffer(this.base); + res.offset = save.offset; + res.length = this.offset; + + this.offset = save.offset; + Reporter.prototype.restore.call(this, save.reporter); + + return res; +}; + +DecoderBuffer.prototype.isEmpty = function isEmpty() { + return this.offset === this.length; +}; + +DecoderBuffer.prototype.readUInt8 = function readUInt8(fail) { + if (this.offset + 1 <= this.length) + return this.base.readUInt8(this.offset++, true); + else + return this.error(fail || 'DecoderBuffer overrun'); +}; + +DecoderBuffer.prototype.skip = function skip(bytes, fail) { + if (!(this.offset + bytes <= this.length)) + return this.error(fail || 'DecoderBuffer overrun'); + + const res = new DecoderBuffer(this.base); + + // Share reporter state + res._reporterState = this._reporterState; + + res.offset = this.offset; + res.length = this.offset + bytes; + this.offset += bytes; + return res; +}; + +DecoderBuffer.prototype.raw = function raw(save) { + return this.base.slice(save ? save.offset : this.offset, this.length); +}; + +function EncoderBuffer(value, reporter) { + if (Array.isArray(value)) { + this.length = 0; + this.value = value.map(function(item) { + if (!EncoderBuffer.isEncoderBuffer(item)) + item = new EncoderBuffer(item, reporter); + this.length += item.length; + return item; + }, this); + } else if (typeof value === 'number') { + if (!(0 <= value && value <= 0xff)) + return reporter.error('non-byte EncoderBuffer value'); + this.value = value; + this.length = 1; + } else if (typeof value === 'string') { + this.value = value; + this.length = Buffer.byteLength(value); + } else if (Buffer.isBuffer(value)) { + this.value = value; + this.length = value.length; + } else { + return reporter.error('Unsupported type: ' + typeof value); + } +} +exports.EncoderBuffer = EncoderBuffer; + +EncoderBuffer.isEncoderBuffer = function isEncoderBuffer(data) { + if (data instanceof EncoderBuffer) { + return true; + } + + // Or accept compatible API + const isCompatible = typeof data === 'object' && + data.constructor.name === 'EncoderBuffer' && + typeof data.length === 'number' && + typeof data.join === 'function'; + + return isCompatible; +}; + +EncoderBuffer.prototype.join = function join(out, offset) { + if (!out) + out = Buffer.alloc(this.length); + if (!offset) + offset = 0; + + if (this.length === 0) + return out; + + if (Array.isArray(this.value)) { + this.value.forEach(function(item) { + item.join(out, offset); + offset += item.length; + }); + } else { + if (typeof this.value === 'number') + out[offset] = this.value; + else if (typeof this.value === 'string') + out.write(this.value, offset); + else if (Buffer.isBuffer(this.value)) + this.value.copy(out, offset); + offset += this.length; + } + + return out; +}; diff --git a/node_modules/asn1.js/lib/asn1/base/index.js b/node_modules/asn1.js/lib/asn1/base/index.js new file mode 100644 index 0000000..8b92f20 --- /dev/null +++ b/node_modules/asn1.js/lib/asn1/base/index.js @@ -0,0 +1,8 @@ +'use strict'; + +const base = exports; + +base.Reporter = require('./reporter').Reporter; +base.DecoderBuffer = require('./buffer').DecoderBuffer; +base.EncoderBuffer = require('./buffer').EncoderBuffer; +base.Node = require('./node'); diff --git a/node_modules/asn1.js/lib/asn1/base/node.js b/node_modules/asn1.js/lib/asn1/base/node.js new file mode 100644 index 0000000..d676d21 --- /dev/null +++ b/node_modules/asn1.js/lib/asn1/base/node.js @@ -0,0 +1,638 @@ +'use strict'; + +const Reporter = require('../base/reporter').Reporter; +const EncoderBuffer = require('../base/buffer').EncoderBuffer; +const DecoderBuffer = require('../base/buffer').DecoderBuffer; +const assert = require('minimalistic-assert'); + +// Supported tags +const tags = [ + 'seq', 'seqof', 'set', 'setof', 'objid', 'bool', + 'gentime', 'utctime', 'null_', 'enum', 'int', 'objDesc', + 'bitstr', 'bmpstr', 'charstr', 'genstr', 'graphstr', 'ia5str', 'iso646str', + 'numstr', 'octstr', 'printstr', 't61str', 'unistr', 'utf8str', 'videostr' +]; + +// Public methods list +const methods = [ + 'key', 'obj', 'use', 'optional', 'explicit', 'implicit', 'def', 'choice', + 'any', 'contains' +].concat(tags); + +// Overrided methods list +const overrided = [ + '_peekTag', '_decodeTag', '_use', + '_decodeStr', '_decodeObjid', '_decodeTime', + '_decodeNull', '_decodeInt', '_decodeBool', '_decodeList', + + '_encodeComposite', '_encodeStr', '_encodeObjid', '_encodeTime', + '_encodeNull', '_encodeInt', '_encodeBool' +]; + +function Node(enc, parent, name) { + const state = {}; + this._baseState = state; + + state.name = name; + state.enc = enc; + + state.parent = parent || null; + state.children = null; + + // State + state.tag = null; + state.args = null; + state.reverseArgs = null; + state.choice = null; + state.optional = false; + state.any = false; + state.obj = false; + state.use = null; + state.useDecoder = null; + state.key = null; + state['default'] = null; + state.explicit = null; + state.implicit = null; + state.contains = null; + + // Should create new instance on each method + if (!state.parent) { + state.children = []; + this._wrap(); + } +} +module.exports = Node; + +const stateProps = [ + 'enc', 'parent', 'children', 'tag', 'args', 'reverseArgs', 'choice', + 'optional', 'any', 'obj', 'use', 'alteredUse', 'key', 'default', 'explicit', + 'implicit', 'contains' +]; + +Node.prototype.clone = function clone() { + const state = this._baseState; + const cstate = {}; + stateProps.forEach(function(prop) { + cstate[prop] = state[prop]; + }); + const res = new this.constructor(cstate.parent); + res._baseState = cstate; + return res; +}; + +Node.prototype._wrap = function wrap() { + const state = this._baseState; + methods.forEach(function(method) { + this[method] = function _wrappedMethod() { + const clone = new this.constructor(this); + state.children.push(clone); + return clone[method].apply(clone, arguments); + }; + }, this); +}; + +Node.prototype._init = function init(body) { + const state = this._baseState; + + assert(state.parent === null); + body.call(this); + + // Filter children + state.children = state.children.filter(function(child) { + return child._baseState.parent === this; + }, this); + assert.equal(state.children.length, 1, 'Root node can have only one child'); +}; + +Node.prototype._useArgs = function useArgs(args) { + const state = this._baseState; + + // Filter children and args + const children = args.filter(function(arg) { + return arg instanceof this.constructor; + }, this); + args = args.filter(function(arg) { + return !(arg instanceof this.constructor); + }, this); + + if (children.length !== 0) { + assert(state.children === null); + state.children = children; + + // Replace parent to maintain backward link + children.forEach(function(child) { + child._baseState.parent = this; + }, this); + } + if (args.length !== 0) { + assert(state.args === null); + state.args = args; + state.reverseArgs = args.map(function(arg) { + if (typeof arg !== 'object' || arg.constructor !== Object) + return arg; + + const res = {}; + Object.keys(arg).forEach(function(key) { + if (key == (key | 0)) + key |= 0; + const value = arg[key]; + res[value] = key; + }); + return res; + }); + } +}; + +// +// Overrided methods +// + +overrided.forEach(function(method) { + Node.prototype[method] = function _overrided() { + const state = this._baseState; + throw new Error(method + ' not implemented for encoding: ' + state.enc); + }; +}); + +// +// Public methods +// + +tags.forEach(function(tag) { + Node.prototype[tag] = function _tagMethod() { + const state = this._baseState; + const args = Array.prototype.slice.call(arguments); + + assert(state.tag === null); + state.tag = tag; + + this._useArgs(args); + + return this; + }; +}); + +Node.prototype.use = function use(item) { + assert(item); + const state = this._baseState; + + assert(state.use === null); + state.use = item; + + return this; +}; + +Node.prototype.optional = function optional() { + const state = this._baseState; + + state.optional = true; + + return this; +}; + +Node.prototype.def = function def(val) { + const state = this._baseState; + + assert(state['default'] === null); + state['default'] = val; + state.optional = true; + + return this; +}; + +Node.prototype.explicit = function explicit(num) { + const state = this._baseState; + + assert(state.explicit === null && state.implicit === null); + state.explicit = num; + + return this; +}; + +Node.prototype.implicit = function implicit(num) { + const state = this._baseState; + + assert(state.explicit === null && state.implicit === null); + state.implicit = num; + + return this; +}; + +Node.prototype.obj = function obj() { + const state = this._baseState; + const args = Array.prototype.slice.call(arguments); + + state.obj = true; + + if (args.length !== 0) + this._useArgs(args); + + return this; +}; + +Node.prototype.key = function key(newKey) { + const state = this._baseState; + + assert(state.key === null); + state.key = newKey; + + return this; +}; + +Node.prototype.any = function any() { + const state = this._baseState; + + state.any = true; + + return this; +}; + +Node.prototype.choice = function choice(obj) { + const state = this._baseState; + + assert(state.choice === null); + state.choice = obj; + this._useArgs(Object.keys(obj).map(function(key) { + return obj[key]; + })); + + return this; +}; + +Node.prototype.contains = function contains(item) { + const state = this._baseState; + + assert(state.use === null); + state.contains = item; + + return this; +}; + +// +// Decoding +// + +Node.prototype._decode = function decode(input, options) { + const state = this._baseState; + + // Decode root node + if (state.parent === null) + return input.wrapResult(state.children[0]._decode(input, options)); + + let result = state['default']; + let present = true; + + let prevKey = null; + if (state.key !== null) + prevKey = input.enterKey(state.key); + + // Check if tag is there + if (state.optional) { + let tag = null; + if (state.explicit !== null) + tag = state.explicit; + else if (state.implicit !== null) + tag = state.implicit; + else if (state.tag !== null) + tag = state.tag; + + if (tag === null && !state.any) { + // Trial and Error + const save = input.save(); + try { + if (state.choice === null) + this._decodeGeneric(state.tag, input, options); + else + this._decodeChoice(input, options); + present = true; + } catch (e) { + present = false; + } + input.restore(save); + } else { + present = this._peekTag(input, tag, state.any); + + if (input.isError(present)) + return present; + } + } + + // Push object on stack + let prevObj; + if (state.obj && present) + prevObj = input.enterObject(); + + if (present) { + // Unwrap explicit values + if (state.explicit !== null) { + const explicit = this._decodeTag(input, state.explicit); + if (input.isError(explicit)) + return explicit; + input = explicit; + } + + const start = input.offset; + + // Unwrap implicit and normal values + if (state.use === null && state.choice === null) { + let save; + if (state.any) + save = input.save(); + const body = this._decodeTag( + input, + state.implicit !== null ? state.implicit : state.tag, + state.any + ); + if (input.isError(body)) + return body; + + if (state.any) + result = input.raw(save); + else + input = body; + } + + if (options && options.track && state.tag !== null) + options.track(input.path(), start, input.length, 'tagged'); + + if (options && options.track && state.tag !== null) + options.track(input.path(), input.offset, input.length, 'content'); + + // Select proper method for tag + if (state.any) { + // no-op + } else if (state.choice === null) { + result = this._decodeGeneric(state.tag, input, options); + } else { + result = this._decodeChoice(input, options); + } + + if (input.isError(result)) + return result; + + // Decode children + if (!state.any && state.choice === null && state.children !== null) { + state.children.forEach(function decodeChildren(child) { + // NOTE: We are ignoring errors here, to let parser continue with other + // parts of encoded data + child._decode(input, options); + }); + } + + // Decode contained/encoded by schema, only in bit or octet strings + if (state.contains && (state.tag === 'octstr' || state.tag === 'bitstr')) { + const data = new DecoderBuffer(result); + result = this._getUse(state.contains, input._reporterState.obj) + ._decode(data, options); + } + } + + // Pop object + if (state.obj && present) + result = input.leaveObject(prevObj); + + // Set key + if (state.key !== null && (result !== null || present === true)) + input.leaveKey(prevKey, state.key, result); + else if (prevKey !== null) + input.exitKey(prevKey); + + return result; +}; + +Node.prototype._decodeGeneric = function decodeGeneric(tag, input, options) { + const state = this._baseState; + + if (tag === 'seq' || tag === 'set') + return null; + if (tag === 'seqof' || tag === 'setof') + return this._decodeList(input, tag, state.args[0], options); + else if (/str$/.test(tag)) + return this._decodeStr(input, tag, options); + else if (tag === 'objid' && state.args) + return this._decodeObjid(input, state.args[0], state.args[1], options); + else if (tag === 'objid') + return this._decodeObjid(input, null, null, options); + else if (tag === 'gentime' || tag === 'utctime') + return this._decodeTime(input, tag, options); + else if (tag === 'null_') + return this._decodeNull(input, options); + else if (tag === 'bool') + return this._decodeBool(input, options); + else if (tag === 'objDesc') + return this._decodeStr(input, tag, options); + else if (tag === 'int' || tag === 'enum') + return this._decodeInt(input, state.args && state.args[0], options); + + if (state.use !== null) { + return this._getUse(state.use, input._reporterState.obj) + ._decode(input, options); + } else { + return input.error('unknown tag: ' + tag); + } +}; + +Node.prototype._getUse = function _getUse(entity, obj) { + + const state = this._baseState; + // Create altered use decoder if implicit is set + state.useDecoder = this._use(entity, obj); + assert(state.useDecoder._baseState.parent === null); + state.useDecoder = state.useDecoder._baseState.children[0]; + if (state.implicit !== state.useDecoder._baseState.implicit) { + state.useDecoder = state.useDecoder.clone(); + state.useDecoder._baseState.implicit = state.implicit; + } + return state.useDecoder; +}; + +Node.prototype._decodeChoice = function decodeChoice(input, options) { + const state = this._baseState; + let result = null; + let match = false; + + Object.keys(state.choice).some(function(key) { + const save = input.save(); + const node = state.choice[key]; + try { + const value = node._decode(input, options); + if (input.isError(value)) + return false; + + result = { type: key, value: value }; + match = true; + } catch (e) { + input.restore(save); + return false; + } + return true; + }, this); + + if (!match) + return input.error('Choice not matched'); + + return result; +}; + +// +// Encoding +// + +Node.prototype._createEncoderBuffer = function createEncoderBuffer(data) { + return new EncoderBuffer(data, this.reporter); +}; + +Node.prototype._encode = function encode(data, reporter, parent) { + const state = this._baseState; + if (state['default'] !== null && state['default'] === data) + return; + + const result = this._encodeValue(data, reporter, parent); + if (result === undefined) + return; + + if (this._skipDefault(result, reporter, parent)) + return; + + return result; +}; + +Node.prototype._encodeValue = function encode(data, reporter, parent) { + const state = this._baseState; + + // Decode root node + if (state.parent === null) + return state.children[0]._encode(data, reporter || new Reporter()); + + let result = null; + + // Set reporter to share it with a child class + this.reporter = reporter; + + // Check if data is there + if (state.optional && data === undefined) { + if (state['default'] !== null) + data = state['default']; + else + return; + } + + // Encode children first + let content = null; + let primitive = false; + if (state.any) { + // Anything that was given is translated to buffer + result = this._createEncoderBuffer(data); + } else if (state.choice) { + result = this._encodeChoice(data, reporter); + } else if (state.contains) { + content = this._getUse(state.contains, parent)._encode(data, reporter); + primitive = true; + } else if (state.children) { + content = state.children.map(function(child) { + if (child._baseState.tag === 'null_') + return child._encode(null, reporter, data); + + if (child._baseState.key === null) + return reporter.error('Child should have a key'); + const prevKey = reporter.enterKey(child._baseState.key); + + if (typeof data !== 'object') + return reporter.error('Child expected, but input is not object'); + + const res = child._encode(data[child._baseState.key], reporter, data); + reporter.leaveKey(prevKey); + + return res; + }, this).filter(function(child) { + return child; + }); + content = this._createEncoderBuffer(content); + } else { + if (state.tag === 'seqof' || state.tag === 'setof') { + // TODO(indutny): this should be thrown on DSL level + if (!(state.args && state.args.length === 1)) + return reporter.error('Too many args for : ' + state.tag); + + if (!Array.isArray(data)) + return reporter.error('seqof/setof, but data is not Array'); + + const child = this.clone(); + child._baseState.implicit = null; + content = this._createEncoderBuffer(data.map(function(item) { + const state = this._baseState; + + return this._getUse(state.args[0], data)._encode(item, reporter); + }, child)); + } else if (state.use !== null) { + result = this._getUse(state.use, parent)._encode(data, reporter); + } else { + content = this._encodePrimitive(state.tag, data); + primitive = true; + } + } + + // Encode data itself + if (!state.any && state.choice === null) { + const tag = state.implicit !== null ? state.implicit : state.tag; + const cls = state.implicit === null ? 'universal' : 'context'; + + if (tag === null) { + if (state.use === null) + reporter.error('Tag could be omitted only for .use()'); + } else { + if (state.use === null) + result = this._encodeComposite(tag, primitive, cls, content); + } + } + + // Wrap in explicit + if (state.explicit !== null) + result = this._encodeComposite(state.explicit, false, 'context', result); + + return result; +}; + +Node.prototype._encodeChoice = function encodeChoice(data, reporter) { + const state = this._baseState; + + const node = state.choice[data.type]; + if (!node) { + assert( + false, + data.type + ' not found in ' + + JSON.stringify(Object.keys(state.choice))); + } + return node._encode(data.value, reporter); +}; + +Node.prototype._encodePrimitive = function encodePrimitive(tag, data) { + const state = this._baseState; + + if (/str$/.test(tag)) + return this._encodeStr(data, tag); + else if (tag === 'objid' && state.args) + return this._encodeObjid(data, state.reverseArgs[0], state.args[1]); + else if (tag === 'objid') + return this._encodeObjid(data, null, null); + else if (tag === 'gentime' || tag === 'utctime') + return this._encodeTime(data, tag); + else if (tag === 'null_') + return this._encodeNull(); + else if (tag === 'int' || tag === 'enum') + return this._encodeInt(data, state.args && state.reverseArgs[0]); + else if (tag === 'bool') + return this._encodeBool(data); + else if (tag === 'objDesc') + return this._encodeStr(data, tag); + else + throw new Error('Unsupported tag: ' + tag); +}; + +Node.prototype._isNumstr = function isNumstr(str) { + return /^[0-9 ]*$/.test(str); +}; + +Node.prototype._isPrintstr = function isPrintstr(str) { + return /^[A-Za-z0-9 '()+,-./:=?]*$/.test(str); +}; diff --git a/node_modules/asn1.js/lib/asn1/base/reporter.js b/node_modules/asn1.js/lib/asn1/base/reporter.js new file mode 100644 index 0000000..d05fe12 --- /dev/null +++ b/node_modules/asn1.js/lib/asn1/base/reporter.js @@ -0,0 +1,123 @@ +'use strict'; + +const inherits = require('inherits'); + +function Reporter(options) { + this._reporterState = { + obj: null, + path: [], + options: options || {}, + errors: [] + }; +} +exports.Reporter = Reporter; + +Reporter.prototype.isError = function isError(obj) { + return obj instanceof ReporterError; +}; + +Reporter.prototype.save = function save() { + const state = this._reporterState; + + return { obj: state.obj, pathLen: state.path.length }; +}; + +Reporter.prototype.restore = function restore(data) { + const state = this._reporterState; + + state.obj = data.obj; + state.path = state.path.slice(0, data.pathLen); +}; + +Reporter.prototype.enterKey = function enterKey(key) { + return this._reporterState.path.push(key); +}; + +Reporter.prototype.exitKey = function exitKey(index) { + const state = this._reporterState; + + state.path = state.path.slice(0, index - 1); +}; + +Reporter.prototype.leaveKey = function leaveKey(index, key, value) { + const state = this._reporterState; + + this.exitKey(index); + if (state.obj !== null) + state.obj[key] = value; +}; + +Reporter.prototype.path = function path() { + return this._reporterState.path.join('/'); +}; + +Reporter.prototype.enterObject = function enterObject() { + const state = this._reporterState; + + const prev = state.obj; + state.obj = {}; + return prev; +}; + +Reporter.prototype.leaveObject = function leaveObject(prev) { + const state = this._reporterState; + + const now = state.obj; + state.obj = prev; + return now; +}; + +Reporter.prototype.error = function error(msg) { + let err; + const state = this._reporterState; + + const inherited = msg instanceof ReporterError; + if (inherited) { + err = msg; + } else { + err = new ReporterError(state.path.map(function(elem) { + return '[' + JSON.stringify(elem) + ']'; + }).join(''), msg.message || msg, msg.stack); + } + + if (!state.options.partial) + throw err; + + if (!inherited) + state.errors.push(err); + + return err; +}; + +Reporter.prototype.wrapResult = function wrapResult(result) { + const state = this._reporterState; + if (!state.options.partial) + return result; + + return { + result: this.isError(result) ? null : result, + errors: state.errors + }; +}; + +function ReporterError(path, msg) { + this.path = path; + this.rethrow(msg); +} +inherits(ReporterError, Error); + +ReporterError.prototype.rethrow = function rethrow(msg) { + this.message = msg + ' at: ' + (this.path || '(shallow)'); + if (Error.captureStackTrace) + Error.captureStackTrace(this, ReporterError); + + if (!this.stack) { + try { + // IE only adds stack when thrown + throw new Error(this.message); + } catch (e) { + this.stack = e.stack; + } + } + return this; +}; diff --git a/node_modules/asn1.js/lib/asn1/constants/der.js b/node_modules/asn1.js/lib/asn1/constants/der.js new file mode 100644 index 0000000..2b678aa --- /dev/null +++ b/node_modules/asn1.js/lib/asn1/constants/der.js @@ -0,0 +1,58 @@ +'use strict'; + +// Helper +function reverse(map) { + const res = {}; + + Object.keys(map).forEach(function(key) { + // Convert key to integer if it is stringified + if ((key | 0) == key) + key = key | 0; + + const value = map[key]; + res[value] = key; + }); + + return res; +} + +exports.tagClass = { + 0: 'universal', + 1: 'application', + 2: 'context', + 3: 'private' +}; +exports.tagClassByName = reverse(exports.tagClass); + +exports.tag = { + 0x00: 'end', + 0x01: 'bool', + 0x02: 'int', + 0x03: 'bitstr', + 0x04: 'octstr', + 0x05: 'null_', + 0x06: 'objid', + 0x07: 'objDesc', + 0x08: 'external', + 0x09: 'real', + 0x0a: 'enum', + 0x0b: 'embed', + 0x0c: 'utf8str', + 0x0d: 'relativeOid', + 0x10: 'seq', + 0x11: 'set', + 0x12: 'numstr', + 0x13: 'printstr', + 0x14: 't61str', + 0x15: 'videostr', + 0x16: 'ia5str', + 0x17: 'utctime', + 0x18: 'gentime', + 0x19: 'graphstr', + 0x1a: 'iso646str', + 0x1b: 'genstr', + 0x1c: 'unistr', + 0x1d: 'charstr', + 0x1e: 'bmpstr' +}; +exports.tagByName = reverse(exports.tag); diff --git a/node_modules/asn1.js/lib/asn1/constants/index.js b/node_modules/asn1.js/lib/asn1/constants/index.js new file mode 100644 index 0000000..632cf3d --- /dev/null +++ b/node_modules/asn1.js/lib/asn1/constants/index.js @@ -0,0 +1,21 @@ +'use strict'; + +const constants = exports; + +// Helper +constants._reverse = function reverse(map) { + const res = {}; + + Object.keys(map).forEach(function(key) { + // Convert key to integer if it is stringified + if ((key | 0) == key) + key = key | 0; + + const value = map[key]; + res[value] = key; + }); + + return res; +}; + +constants.der = require('./der'); diff --git a/node_modules/asn1.js/lib/asn1/decoders/der.js b/node_modules/asn1.js/lib/asn1/decoders/der.js new file mode 100644 index 0000000..c5b0515 --- /dev/null +++ b/node_modules/asn1.js/lib/asn1/decoders/der.js @@ -0,0 +1,335 @@ +'use strict'; + +const inherits = require('inherits'); + +const bignum = require('bn.js'); +const DecoderBuffer = require('../base/buffer').DecoderBuffer; +const Node = require('../base/node'); + +// Import DER constants +const der = require('../constants/der'); + +function DERDecoder(entity) { + this.enc = 'der'; + this.name = entity.name; + this.entity = entity; + + // Construct base tree + this.tree = new DERNode(); + this.tree._init(entity.body); +} +module.exports = DERDecoder; + +DERDecoder.prototype.decode = function decode(data, options) { + if (!DecoderBuffer.isDecoderBuffer(data)) { + data = new DecoderBuffer(data, options); + } + + return this.tree._decode(data, options); +}; + +// Tree methods + +function DERNode(parent) { + Node.call(this, 'der', parent); +} +inherits(DERNode, Node); + +DERNode.prototype._peekTag = function peekTag(buffer, tag, any) { + if (buffer.isEmpty()) + return false; + + const state = buffer.save(); + const decodedTag = derDecodeTag(buffer, 'Failed to peek tag: "' + tag + '"'); + if (buffer.isError(decodedTag)) + return decodedTag; + + buffer.restore(state); + + return decodedTag.tag === tag || decodedTag.tagStr === tag || + (decodedTag.tagStr + 'of') === tag || any; +}; + +DERNode.prototype._decodeTag = function decodeTag(buffer, tag, any) { + const decodedTag = derDecodeTag(buffer, + 'Failed to decode tag of "' + tag + '"'); + if (buffer.isError(decodedTag)) + return decodedTag; + + let len = derDecodeLen(buffer, + decodedTag.primitive, + 'Failed to get length of "' + tag + '"'); + + // Failure + if (buffer.isError(len)) + return len; + + if (!any && + decodedTag.tag !== tag && + decodedTag.tagStr !== tag && + decodedTag.tagStr + 'of' !== tag) { + return buffer.error('Failed to match tag: "' + tag + '"'); + } + + if (decodedTag.primitive || len !== null) + return buffer.skip(len, 'Failed to match body of: "' + tag + '"'); + + // Indefinite length... find END tag + const state = buffer.save(); + const res = this._skipUntilEnd( + buffer, + 'Failed to skip indefinite length body: "' + this.tag + '"'); + if (buffer.isError(res)) + return res; + + len = buffer.offset - state.offset; + buffer.restore(state); + return buffer.skip(len, 'Failed to match body of: "' + tag + '"'); +}; + +DERNode.prototype._skipUntilEnd = function skipUntilEnd(buffer, fail) { + for (;;) { + const tag = derDecodeTag(buffer, fail); + if (buffer.isError(tag)) + return tag; + const len = derDecodeLen(buffer, tag.primitive, fail); + if (buffer.isError(len)) + return len; + + let res; + if (tag.primitive || len !== null) + res = buffer.skip(len); + else + res = this._skipUntilEnd(buffer, fail); + + // Failure + if (buffer.isError(res)) + return res; + + if (tag.tagStr === 'end') + break; + } +}; + +DERNode.prototype._decodeList = function decodeList(buffer, tag, decoder, + options) { + const result = []; + while (!buffer.isEmpty()) { + const possibleEnd = this._peekTag(buffer, 'end'); + if (buffer.isError(possibleEnd)) + return possibleEnd; + + const res = decoder.decode(buffer, 'der', options); + if (buffer.isError(res) && possibleEnd) + break; + result.push(res); + } + return result; +}; + +DERNode.prototype._decodeStr = function decodeStr(buffer, tag) { + if (tag === 'bitstr') { + const unused = buffer.readUInt8(); + if (buffer.isError(unused)) + return unused; + return { unused: unused, data: buffer.raw() }; + } else if (tag === 'bmpstr') { + const raw = buffer.raw(); + if (raw.length % 2 === 1) + return buffer.error('Decoding of string type: bmpstr length mismatch'); + + let str = ''; + for (let i = 0; i < raw.length / 2; i++) { + str += String.fromCharCode(raw.readUInt16BE(i * 2)); + } + return str; + } else if (tag === 'numstr') { + const numstr = buffer.raw().toString('ascii'); + if (!this._isNumstr(numstr)) { + return buffer.error('Decoding of string type: ' + + 'numstr unsupported characters'); + } + return numstr; + } else if (tag === 'octstr') { + return buffer.raw(); + } else if (tag === 'objDesc') { + return buffer.raw(); + } else if (tag === 'printstr') { + const printstr = buffer.raw().toString('ascii'); + if (!this._isPrintstr(printstr)) { + return buffer.error('Decoding of string type: ' + + 'printstr unsupported characters'); + } + return printstr; + } else if (/str$/.test(tag)) { + return buffer.raw().toString(); + } else { + return buffer.error('Decoding of string type: ' + tag + ' unsupported'); + } +}; + +DERNode.prototype._decodeObjid = function decodeObjid(buffer, values, relative) { + let result; + const identifiers = []; + let ident = 0; + let subident = 0; + while (!buffer.isEmpty()) { + subident = buffer.readUInt8(); + ident <<= 7; + ident |= subident & 0x7f; + if ((subident & 0x80) === 0) { + identifiers.push(ident); + ident = 0; + } + } + if (subident & 0x80) + identifiers.push(ident); + + const first = (identifiers[0] / 40) | 0; + const second = identifiers[0] % 40; + + if (relative) + result = identifiers; + else + result = [first, second].concat(identifiers.slice(1)); + + if (values) { + let tmp = values[result.join(' ')]; + if (tmp === undefined) + tmp = values[result.join('.')]; + if (tmp !== undefined) + result = tmp; + } + + return result; +}; + +DERNode.prototype._decodeTime = function decodeTime(buffer, tag) { + const str = buffer.raw().toString(); + + let year; + let mon; + let day; + let hour; + let min; + let sec; + if (tag === 'gentime') { + year = str.slice(0, 4) | 0; + mon = str.slice(4, 6) | 0; + day = str.slice(6, 8) | 0; + hour = str.slice(8, 10) | 0; + min = str.slice(10, 12) | 0; + sec = str.slice(12, 14) | 0; + } else if (tag === 'utctime') { + year = str.slice(0, 2) | 0; + mon = str.slice(2, 4) | 0; + day = str.slice(4, 6) | 0; + hour = str.slice(6, 8) | 0; + min = str.slice(8, 10) | 0; + sec = str.slice(10, 12) | 0; + if (year < 70) + year = 2000 + year; + else + year = 1900 + year; + } else { + return buffer.error('Decoding ' + tag + ' time is not supported yet'); + } + + return Date.UTC(year, mon - 1, day, hour, min, sec, 0); +}; + +DERNode.prototype._decodeNull = function decodeNull() { + return null; +}; + +DERNode.prototype._decodeBool = function decodeBool(buffer) { + const res = buffer.readUInt8(); + if (buffer.isError(res)) + return res; + else + return res !== 0; +}; + +DERNode.prototype._decodeInt = function decodeInt(buffer, values) { + // Bigint, return as it is (assume big endian) + const raw = buffer.raw(); + let res = new bignum(raw); + + if (values) + res = values[res.toString(10)] || res; + + return res; +}; + +DERNode.prototype._use = function use(entity, obj) { + if (typeof entity === 'function') + entity = entity(obj); + return entity._getDecoder('der').tree; +}; + +// Utility methods + +function derDecodeTag(buf, fail) { + let tag = buf.readUInt8(fail); + if (buf.isError(tag)) + return tag; + + const cls = der.tagClass[tag >> 6]; + const primitive = (tag & 0x20) === 0; + + // Multi-octet tag - load + if ((tag & 0x1f) === 0x1f) { + let oct = tag; + tag = 0; + while ((oct & 0x80) === 0x80) { + oct = buf.readUInt8(fail); + if (buf.isError(oct)) + return oct; + + tag <<= 7; + tag |= oct & 0x7f; + } + } else { + tag &= 0x1f; + } + const tagStr = der.tag[tag]; + + return { + cls: cls, + primitive: primitive, + tag: tag, + tagStr: tagStr + }; +} + +function derDecodeLen(buf, primitive, fail) { + let len = buf.readUInt8(fail); + if (buf.isError(len)) + return len; + + // Indefinite form + if (!primitive && len === 0x80) + return null; + + // Definite form + if ((len & 0x80) === 0) { + // Short form + return len; + } + + // Long form + const num = len & 0x7f; + if (num > 4) + return buf.error('length octect is too long'); + + len = 0; + for (let i = 0; i < num; i++) { + len <<= 8; + const j = buf.readUInt8(fail); + if (buf.isError(j)) + return j; + len |= j; + } + + return len; +} diff --git a/node_modules/asn1.js/lib/asn1/decoders/index.js b/node_modules/asn1.js/lib/asn1/decoders/index.js new file mode 100644 index 0000000..14fb05a --- /dev/null +++ b/node_modules/asn1.js/lib/asn1/decoders/index.js @@ -0,0 +1,6 @@ +'use strict'; + +const decoders = exports; + +decoders.der = require('./der'); +decoders.pem = require('./pem'); diff --git a/node_modules/asn1.js/lib/asn1/decoders/pem.js b/node_modules/asn1.js/lib/asn1/decoders/pem.js new file mode 100644 index 0000000..2b050ef --- /dev/null +++ b/node_modules/asn1.js/lib/asn1/decoders/pem.js @@ -0,0 +1,51 @@ +'use strict'; + +const inherits = require('inherits'); +const Buffer = require('safer-buffer').Buffer; + +const DERDecoder = require('./der'); + +function PEMDecoder(entity) { + DERDecoder.call(this, entity); + this.enc = 'pem'; +} +inherits(PEMDecoder, DERDecoder); +module.exports = PEMDecoder; + +PEMDecoder.prototype.decode = function decode(data, options) { + const lines = data.toString().split(/[\r\n]+/g); + + const label = options.label.toUpperCase(); + + const re = /^-----(BEGIN|END) ([^-]+)-----$/; + let start = -1; + let end = -1; + for (let i = 0; i < lines.length; i++) { + const match = lines[i].match(re); + if (match === null) + continue; + + if (match[2] !== label) + continue; + + if (start === -1) { + if (match[1] !== 'BEGIN') + break; + start = i; + } else { + if (match[1] !== 'END') + break; + end = i; + break; + } + } + if (start === -1 || end === -1) + throw new Error('PEM section not found for: ' + label); + + const base64 = lines.slice(start + 1, end).join(''); + // Remove excessive symbols + base64.replace(/[^a-z0-9+/=]+/gi, ''); + + const input = Buffer.from(base64, 'base64'); + return DERDecoder.prototype.decode.call(this, input, options); +}; diff --git a/node_modules/asn1.js/lib/asn1/encoders/der.js b/node_modules/asn1.js/lib/asn1/encoders/der.js new file mode 100644 index 0000000..55eb435 --- /dev/null +++ b/node_modules/asn1.js/lib/asn1/encoders/der.js @@ -0,0 +1,295 @@ +'use strict'; + +const inherits = require('inherits'); +const Buffer = require('safer-buffer').Buffer; +const Node = require('../base/node'); + +// Import DER constants +const der = require('../constants/der'); + +function DEREncoder(entity) { + this.enc = 'der'; + this.name = entity.name; + this.entity = entity; + + // Construct base tree + this.tree = new DERNode(); + this.tree._init(entity.body); +} +module.exports = DEREncoder; + +DEREncoder.prototype.encode = function encode(data, reporter) { + return this.tree._encode(data, reporter).join(); +}; + +// Tree methods + +function DERNode(parent) { + Node.call(this, 'der', parent); +} +inherits(DERNode, Node); + +DERNode.prototype._encodeComposite = function encodeComposite(tag, + primitive, + cls, + content) { + const encodedTag = encodeTag(tag, primitive, cls, this.reporter); + + // Short form + if (content.length < 0x80) { + const header = Buffer.alloc(2); + header[0] = encodedTag; + header[1] = content.length; + return this._createEncoderBuffer([ header, content ]); + } + + // Long form + // Count octets required to store length + let lenOctets = 1; + for (let i = content.length; i >= 0x100; i >>= 8) + lenOctets++; + + const header = Buffer.alloc(1 + 1 + lenOctets); + header[0] = encodedTag; + header[1] = 0x80 | lenOctets; + + for (let i = 1 + lenOctets, j = content.length; j > 0; i--, j >>= 8) + header[i] = j & 0xff; + + return this._createEncoderBuffer([ header, content ]); +}; + +DERNode.prototype._encodeStr = function encodeStr(str, tag) { + if (tag === 'bitstr') { + return this._createEncoderBuffer([ str.unused | 0, str.data ]); + } else if (tag === 'bmpstr') { + const buf = Buffer.alloc(str.length * 2); + for (let i = 0; i < str.length; i++) { + buf.writeUInt16BE(str.charCodeAt(i), i * 2); + } + return this._createEncoderBuffer(buf); + } else if (tag === 'numstr') { + if (!this._isNumstr(str)) { + return this.reporter.error('Encoding of string type: numstr supports ' + + 'only digits and space'); + } + return this._createEncoderBuffer(str); + } else if (tag === 'printstr') { + if (!this._isPrintstr(str)) { + return this.reporter.error('Encoding of string type: printstr supports ' + + 'only latin upper and lower case letters, ' + + 'digits, space, apostrophe, left and rigth ' + + 'parenthesis, plus sign, comma, hyphen, ' + + 'dot, slash, colon, equal sign, ' + + 'question mark'); + } + return this._createEncoderBuffer(str); + } else if (/str$/.test(tag)) { + return this._createEncoderBuffer(str); + } else if (tag === 'objDesc') { + return this._createEncoderBuffer(str); + } else { + return this.reporter.error('Encoding of string type: ' + tag + + ' unsupported'); + } +}; + +DERNode.prototype._encodeObjid = function encodeObjid(id, values, relative) { + if (typeof id === 'string') { + if (!values) + return this.reporter.error('string objid given, but no values map found'); + if (!values.hasOwnProperty(id)) + return this.reporter.error('objid not found in values map'); + id = values[id].split(/[\s.]+/g); + for (let i = 0; i < id.length; i++) + id[i] |= 0; + } else if (Array.isArray(id)) { + id = id.slice(); + for (let i = 0; i < id.length; i++) + id[i] |= 0; + } + + if (!Array.isArray(id)) { + return this.reporter.error('objid() should be either array or string, ' + + 'got: ' + JSON.stringify(id)); + } + + if (!relative) { + if (id[1] >= 40) + return this.reporter.error('Second objid identifier OOB'); + id.splice(0, 2, id[0] * 40 + id[1]); + } + + // Count number of octets + let size = 0; + for (let i = 0; i < id.length; i++) { + let ident = id[i]; + for (size++; ident >= 0x80; ident >>= 7) + size++; + } + + const objid = Buffer.alloc(size); + let offset = objid.length - 1; + for (let i = id.length - 1; i >= 0; i--) { + let ident = id[i]; + objid[offset--] = ident & 0x7f; + while ((ident >>= 7) > 0) + objid[offset--] = 0x80 | (ident & 0x7f); + } + + return this._createEncoderBuffer(objid); +}; + +function two(num) { + if (num < 10) + return '0' + num; + else + return num; +} + +DERNode.prototype._encodeTime = function encodeTime(time, tag) { + let str; + const date = new Date(time); + + if (tag === 'gentime') { + str = [ + two(date.getUTCFullYear()), + two(date.getUTCMonth() + 1), + two(date.getUTCDate()), + two(date.getUTCHours()), + two(date.getUTCMinutes()), + two(date.getUTCSeconds()), + 'Z' + ].join(''); + } else if (tag === 'utctime') { + str = [ + two(date.getUTCFullYear() % 100), + two(date.getUTCMonth() + 1), + two(date.getUTCDate()), + two(date.getUTCHours()), + two(date.getUTCMinutes()), + two(date.getUTCSeconds()), + 'Z' + ].join(''); + } else { + this.reporter.error('Encoding ' + tag + ' time is not supported yet'); + } + + return this._encodeStr(str, 'octstr'); +}; + +DERNode.prototype._encodeNull = function encodeNull() { + return this._createEncoderBuffer(''); +}; + +DERNode.prototype._encodeInt = function encodeInt(num, values) { + if (typeof num === 'string') { + if (!values) + return this.reporter.error('String int or enum given, but no values map'); + if (!values.hasOwnProperty(num)) { + return this.reporter.error('Values map doesn\'t contain: ' + + JSON.stringify(num)); + } + num = values[num]; + } + + // Bignum, assume big endian + if (typeof num !== 'number' && !Buffer.isBuffer(num)) { + const numArray = num.toArray(); + if (!num.sign && numArray[0] & 0x80) { + numArray.unshift(0); + } + num = Buffer.from(numArray); + } + + if (Buffer.isBuffer(num)) { + let size = num.length; + if (num.length === 0) + size++; + + const out = Buffer.alloc(size); + num.copy(out); + if (num.length === 0) + out[0] = 0; + return this._createEncoderBuffer(out); + } + + if (num < 0x80) + return this._createEncoderBuffer(num); + + if (num < 0x100) + return this._createEncoderBuffer([0, num]); + + let size = 1; + for (let i = num; i >= 0x100; i >>= 8) + size++; + + const out = new Array(size); + for (let i = out.length - 1; i >= 0; i--) { + out[i] = num & 0xff; + num >>= 8; + } + if(out[0] & 0x80) { + out.unshift(0); + } + + return this._createEncoderBuffer(Buffer.from(out)); +}; + +DERNode.prototype._encodeBool = function encodeBool(value) { + return this._createEncoderBuffer(value ? 0xff : 0); +}; + +DERNode.prototype._use = function use(entity, obj) { + if (typeof entity === 'function') + entity = entity(obj); + return entity._getEncoder('der').tree; +}; + +DERNode.prototype._skipDefault = function skipDefault(dataBuffer, reporter, parent) { + const state = this._baseState; + let i; + if (state['default'] === null) + return false; + + const data = dataBuffer.join(); + if (state.defaultBuffer === undefined) + state.defaultBuffer = this._encodeValue(state['default'], reporter, parent).join(); + + if (data.length !== state.defaultBuffer.length) + return false; + + for (i=0; i < data.length; i++) + if (data[i] !== state.defaultBuffer[i]) + return false; + + return true; +}; + +// Utility methods + +function encodeTag(tag, primitive, cls, reporter) { + let res; + + if (tag === 'seqof') + tag = 'seq'; + else if (tag === 'setof') + tag = 'set'; + + if (der.tagByName.hasOwnProperty(tag)) + res = der.tagByName[tag]; + else if (typeof tag === 'number' && (tag | 0) === tag) + res = tag; + else + return reporter.error('Unknown tag: ' + tag); + + if (res >= 0x1f) + return reporter.error('Multi-octet tag encoding unsupported'); + + if (!primitive) + res |= 0x20; + + res |= (der.tagClassByName[cls || 'universal'] << 6); + + return res; +} diff --git a/node_modules/asn1.js/lib/asn1/encoders/index.js b/node_modules/asn1.js/lib/asn1/encoders/index.js new file mode 100644 index 0000000..bb8ea34 --- /dev/null +++ b/node_modules/asn1.js/lib/asn1/encoders/index.js @@ -0,0 +1,6 @@ +'use strict'; + +const encoders = exports; + +encoders.der = require('./der'); +encoders.pem = require('./pem'); diff --git a/node_modules/asn1.js/lib/asn1/encoders/pem.js b/node_modules/asn1.js/lib/asn1/encoders/pem.js new file mode 100644 index 0000000..77fbdb4 --- /dev/null +++ b/node_modules/asn1.js/lib/asn1/encoders/pem.js @@ -0,0 +1,23 @@ +'use strict'; + +const inherits = require('inherits'); + +const DEREncoder = require('./der'); + +function PEMEncoder(entity) { + DEREncoder.call(this, entity); + this.enc = 'pem'; +} +inherits(PEMEncoder, DEREncoder); +module.exports = PEMEncoder; + +PEMEncoder.prototype.encode = function encode(data, options) { + const buf = DEREncoder.prototype.encode.call(this, data); + + const p = buf.toString('base64'); + const out = [ '-----BEGIN ' + options.label + '-----' ]; + for (let i = 0; i < p.length; i += 64) + out.push(p.slice(i, i + 64)); + out.push('-----END ' + options.label + '-----'); + return out.join('\n'); +}; diff --git a/node_modules/asn1.js/package.json b/node_modules/asn1.js/package.json new file mode 100644 index 0000000..66778ad --- /dev/null +++ b/node_modules/asn1.js/package.json @@ -0,0 +1,63 @@ +{ + "_from": "asn1.js@^5.3.0", + "_id": "asn1.js@5.4.1", + "_inBundle": false, + "_integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "_location": "/asn1.js", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "asn1.js@^5.3.0", + "name": "asn1.js", + "escapedName": "asn1.js", + "rawSpec": "^5.3.0", + "saveSpec": null, + "fetchSpec": "^5.3.0" + }, + "_requiredBy": [ + "/web-push" + ], + "_resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "_shasum": "11a980b84ebb91781ce35b0fdc2ee294e3783f07", + "_spec": "asn1.js@^5.3.0", + "_where": "D:\\Users\\user\\Documents\\Portofolio\\Github\\WebsiteFootballPWA\\node_modules\\web-push", + "author": { + "name": "Fedor Indutny" + }, + "bugs": { + "url": "https://github.com/indutny/asn1.js/issues" + }, + "bundleDependencies": false, + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + }, + "deprecated": false, + "description": "ASN.1 encoder and decoder", + "devDependencies": { + "eslint": "^4.10.0", + "mocha": "^7.0.0" + }, + "homepage": "https://github.com/indutny/asn1.js", + "keywords": [ + "asn.1", + "der" + ], + "license": "MIT", + "main": "lib/asn1.js", + "name": "asn1.js", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/indutny/asn1.js.git" + }, + "scripts": { + "lint": "eslint --fix lib/*.js lib/**/*.js lib/**/**/*.js && npm run lint-2560 && npm run lint-5280", + "lint-2560": "eslint --fix rfc/2560/*.js rfc/2560/test/*.js", + "lint-5280": "eslint --fix rfc/5280/*.js rfc/5280/test/*.js", + "test": "mocha --reporter spec test/*-test.js && cd rfc/2560 && npm i && npm test && cd ../../rfc/5280 && npm i && npm test && cd ../../ && npm run lint" + }, + "version": "5.4.1" +} diff --git a/node_modules/bn.js/README.md b/node_modules/bn.js/README.md new file mode 100644 index 0000000..370f06d --- /dev/null +++ b/node_modules/bn.js/README.md @@ -0,0 +1,221 @@ +# bn.js + +> BigNum in pure javascript + +[![Build Status](https://secure.travis-ci.org/indutny/bn.js.png)](http://travis-ci.org/indutny/bn.js) + +## Install +`npm install --save bn.js` + +## Usage + +```js +const BN = require('bn.js'); + +var a = new BN('dead', 16); +var b = new BN('101010', 2); + +var res = a.add(b); +console.log(res.toString(10)); // 57047 +``` + +**Note**: decimals are not supported in this library. + +## Notation + +### Prefixes + +There are several prefixes to instructions that affect the way the work. Here +is the list of them in the order of appearance in the function name: + +* `i` - perform operation in-place, storing the result in the host object (on + which the method was invoked). Might be used to avoid number allocation costs +* `u` - unsigned, ignore the sign of operands when performing operation, or + always return positive value. Second case applies to reduction operations + like `mod()`. In such cases if the result will be negative - modulo will be + added to the result to make it positive + +### Postfixes + +The only available postfix at the moment is: + +* `n` - which means that the argument of the function must be a plain JavaScript + Number. Decimals are not supported. + +### Examples + +* `a.iadd(b)` - perform addition on `a` and `b`, storing the result in `a` +* `a.umod(b)` - reduce `a` modulo `b`, returning positive value +* `a.iushln(13)` - shift bits of `a` left by 13 + +## Instructions + +Prefixes/postfixes are put in parens at the of the line. `endian` - could be +either `le` (little-endian) or `be` (big-endian). + +### Utilities + +* `a.clone()` - clone number +* `a.toString(base, length)` - convert to base-string and pad with zeroes +* `a.toNumber()` - convert to Javascript Number (limited to 53 bits) +* `a.toJSON()` - convert to JSON compatible hex string (alias of `toString(16)`) +* `a.toArray(endian, length)` - convert to byte `Array`, and optionally zero + pad to length, throwing if already exceeding +* `a.toArrayLike(type, endian, length)` - convert to an instance of `type`, + which must behave like an `Array` +* `a.toBuffer(endian, length)` - convert to Node.js Buffer (if available). For + compatibility with browserify and similar tools, use this instead: + `a.toArrayLike(Buffer, endian, length)` +* `a.bitLength()` - get number of bits occupied +* `a.zeroBits()` - return number of less-significant consequent zero bits + (example: `1010000` has 4 zero bits) +* `a.byteLength()` - return number of bytes occupied +* `a.isNeg()` - true if the number is negative +* `a.isEven()` - no comments +* `a.isOdd()` - no comments +* `a.isZero()` - no comments +* `a.cmp(b)` - compare numbers and return `-1` (a `<` b), `0` (a `==` b), or `1` (a `>` b) + depending on the comparison result (`ucmp`, `cmpn`) +* `a.lt(b)` - `a` less than `b` (`n`) +* `a.lte(b)` - `a` less than or equals `b` (`n`) +* `a.gt(b)` - `a` greater than `b` (`n`) +* `a.gte(b)` - `a` greater than or equals `b` (`n`) +* `a.eq(b)` - `a` equals `b` (`n`) +* `a.toTwos(width)` - convert to two's complement representation, where `width` is bit width +* `a.fromTwos(width)` - convert from two's complement representation, where `width` is the bit width +* `BN.isBN(object)` - returns true if the supplied `object` is a BN.js instance + +### Arithmetics + +* `a.neg()` - negate sign (`i`) +* `a.abs()` - absolute value (`i`) +* `a.add(b)` - addition (`i`, `n`, `in`) +* `a.sub(b)` - subtraction (`i`, `n`, `in`) +* `a.mul(b)` - multiply (`i`, `n`, `in`) +* `a.sqr()` - square (`i`) +* `a.pow(b)` - raise `a` to the power of `b` +* `a.div(b)` - divide (`divn`, `idivn`) +* `a.mod(b)` - reduct (`u`, `n`) (but no `umodn`) +* `a.divRound(b)` - rounded division + +### Bit operations + +* `a.or(b)` - or (`i`, `u`, `iu`) +* `a.and(b)` - and (`i`, `u`, `iu`, `andln`) (NOTE: `andln` is going to be replaced + with `andn` in future) +* `a.xor(b)` - xor (`i`, `u`, `iu`) +* `a.setn(b)` - set specified bit to `1` +* `a.shln(b)` - shift left (`i`, `u`, `iu`) +* `a.shrn(b)` - shift right (`i`, `u`, `iu`) +* `a.testn(b)` - test if specified bit is set +* `a.maskn(b)` - clear bits with indexes higher or equal to `b` (`i`) +* `a.bincn(b)` - add `1 << b` to the number +* `a.notn(w)` - not (for the width specified by `w`) (`i`) + +### Reduction + +* `a.gcd(b)` - GCD +* `a.egcd(b)` - Extended GCD results (`{ a: ..., b: ..., gcd: ... }`) +* `a.invm(b)` - inverse `a` modulo `b` + +## Fast reduction + +When doing lots of reductions using the same modulo, it might be beneficial to +use some tricks: like [Montgomery multiplication][0], or using special algorithm +for [Mersenne Prime][1]. + +### Reduction context + +To enable this tricks one should create a reduction context: + +```js +var red = BN.red(num); +``` +where `num` is just a BN instance. + +Or: + +```js +var red = BN.red(primeName); +``` + +Where `primeName` is either of these [Mersenne Primes][1]: + +* `'k256'` +* `'p224'` +* `'p192'` +* `'p25519'` + +Or: + +```js +var red = BN.mont(num); +``` + +To reduce numbers with [Montgomery trick][0]. `.mont()` is generally faster than +`.red(num)`, but slower than `BN.red(primeName)`. + +### Converting numbers + +Before performing anything in reduction context - numbers should be converted +to it. Usually, this means that one should: + +* Convert inputs to reducted ones +* Operate on them in reduction context +* Convert outputs back from the reduction context + +Here is how one may convert numbers to `red`: + +```js +var redA = a.toRed(red); +``` +Where `red` is a reduction context created using instructions above + +Here is how to convert them back: + +```js +var a = redA.fromRed(); +``` + +### Red instructions + +Most of the instructions from the very start of this readme have their +counterparts in red context: + +* `a.redAdd(b)`, `a.redIAdd(b)` +* `a.redSub(b)`, `a.redISub(b)` +* `a.redShl(num)` +* `a.redMul(b)`, `a.redIMul(b)` +* `a.redSqr()`, `a.redISqr()` +* `a.redSqrt()` - square root modulo reduction context's prime +* `a.redInvm()` - modular inverse of the number +* `a.redNeg()` +* `a.redPow(b)` - modular exponentiation + +## LICENSE + +This software is licensed under the MIT License. + +Copyright Fedor Indutny, 2015. + +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. + +[0]: https://en.wikipedia.org/wiki/Montgomery_modular_multiplication +[1]: https://en.wikipedia.org/wiki/Mersenne_prime diff --git a/node_modules/bn.js/lib/bn.js b/node_modules/bn.js/lib/bn.js new file mode 100644 index 0000000..855dfa6 --- /dev/null +++ b/node_modules/bn.js/lib/bn.js @@ -0,0 +1,3433 @@ +(function (module, exports) { + 'use strict'; + + // Utils + function assert (val, msg) { + if (!val) throw new Error(msg || 'Assertion failed'); + } + + // Could use `inherits` module, but don't want to move from single file + // architecture yet. + function inherits (ctor, superCtor) { + ctor.super_ = superCtor; + var TempCtor = function () {}; + TempCtor.prototype = superCtor.prototype; + ctor.prototype = new TempCtor(); + ctor.prototype.constructor = ctor; + } + + // BN + + function BN (number, base, endian) { + if (BN.isBN(number)) { + return number; + } + + this.negative = 0; + this.words = null; + this.length = 0; + + // Reduction context + this.red = null; + + if (number !== null) { + if (base === 'le' || base === 'be') { + endian = base; + base = 10; + } + + this._init(number || 0, base || 10, endian || 'be'); + } + } + if (typeof module === 'object') { + module.exports = BN; + } else { + exports.BN = BN; + } + + BN.BN = BN; + BN.wordSize = 26; + + var Buffer; + try { + Buffer = require('buffer').Buffer; + } catch (e) { + } + + BN.isBN = function isBN (num) { + if (num instanceof BN) { + return true; + } + + return num !== null && typeof num === 'object' && + num.constructor.wordSize === BN.wordSize && Array.isArray(num.words); + }; + + BN.max = function max (left, right) { + if (left.cmp(right) > 0) return left; + return right; + }; + + BN.min = function min (left, right) { + if (left.cmp(right) < 0) return left; + return right; + }; + + BN.prototype._init = function init (number, base, endian) { + if (typeof number === 'number') { + return this._initNumber(number, base, endian); + } + + if (typeof number === 'object') { + return this._initArray(number, base, endian); + } + + if (base === 'hex') { + base = 16; + } + assert(base === (base | 0) && base >= 2 && base <= 36); + + number = number.toString().replace(/\s+/g, ''); + var start = 0; + if (number[0] === '-') { + start++; + } + + if (base === 16) { + this._parseHex(number, start); + } else { + this._parseBase(number, base, start); + } + + if (number[0] === '-') { + this.negative = 1; + } + + this.strip(); + + if (endian !== 'le') return; + + this._initArray(this.toArray(), base, endian); + }; + + BN.prototype._initNumber = function _initNumber (number, base, endian) { + if (number < 0) { + this.negative = 1; + number = -number; + } + if (number < 0x4000000) { + this.words = [ number & 0x3ffffff ]; + this.length = 1; + } else if (number < 0x10000000000000) { + this.words = [ + number & 0x3ffffff, + (number / 0x4000000) & 0x3ffffff + ]; + this.length = 2; + } else { + assert(number < 0x20000000000000); // 2 ^ 53 (unsafe) + this.words = [ + number & 0x3ffffff, + (number / 0x4000000) & 0x3ffffff, + 1 + ]; + this.length = 3; + } + + if (endian !== 'le') return; + + // Reverse the bytes + this._initArray(this.toArray(), base, endian); + }; + + BN.prototype._initArray = function _initArray (number, base, endian) { + // Perhaps a Uint8Array + assert(typeof number.length === 'number'); + if (number.length <= 0) { + this.words = [ 0 ]; + this.length = 1; + return this; + } + + this.length = Math.ceil(number.length / 3); + this.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + this.words[i] = 0; + } + + var j, w; + var off = 0; + if (endian === 'be') { + for (i = number.length - 1, j = 0; i >= 0; i -= 3) { + w = number[i] | (number[i - 1] << 8) | (number[i - 2] << 16); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + } else if (endian === 'le') { + for (i = 0, j = 0; i < number.length; i += 3) { + w = number[i] | (number[i + 1] << 8) | (number[i + 2] << 16); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] = (w >>> (26 - off)) & 0x3ffffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + } + return this.strip(); + }; + + function parseHex (str, start, end) { + var r = 0; + var len = Math.min(str.length, end); + for (var i = start; i < len; i++) { + var c = str.charCodeAt(i) - 48; + + r <<= 4; + + // 'a' - 'f' + if (c >= 49 && c <= 54) { + r |= c - 49 + 0xa; + + // 'A' - 'F' + } else if (c >= 17 && c <= 22) { + r |= c - 17 + 0xa; + + // '0' - '9' + } else { + r |= c & 0xf; + } + } + return r; + } + + BN.prototype._parseHex = function _parseHex (number, start) { + // Create possibly bigger array to ensure that it fits the number + this.length = Math.ceil((number.length - start) / 6); + this.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + this.words[i] = 0; + } + + var j, w; + // Scan 24-bit chunks and add them to the number + var off = 0; + for (i = number.length - 6, j = 0; i >= start; i -= 6) { + w = parseHex(number, i, i + 6); + this.words[j] |= (w << off) & 0x3ffffff; + // NOTE: `0x3fffff` is intentional here, 26bits max shift + 24bit hex limb + this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; + off += 24; + if (off >= 26) { + off -= 26; + j++; + } + } + if (i + 6 !== start) { + w = parseHex(number, start, i + 6); + this.words[j] |= (w << off) & 0x3ffffff; + this.words[j + 1] |= w >>> (26 - off) & 0x3fffff; + } + this.strip(); + }; + + function parseBase (str, start, end, mul) { + var r = 0; + var len = Math.min(str.length, end); + for (var i = start; i < len; i++) { + var c = str.charCodeAt(i) - 48; + + r *= mul; + + // 'a' + if (c >= 49) { + r += c - 49 + 0xa; + + // 'A' + } else if (c >= 17) { + r += c - 17 + 0xa; + + // '0' - '9' + } else { + r += c; + } + } + return r; + } + + BN.prototype._parseBase = function _parseBase (number, base, start) { + // Initialize as zero + this.words = [ 0 ]; + this.length = 1; + + // Find length of limb in base + for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) { + limbLen++; + } + limbLen--; + limbPow = (limbPow / base) | 0; + + var total = number.length - start; + var mod = total % limbLen; + var end = Math.min(total, total - mod) + start; + + var word = 0; + for (var i = start; i < end; i += limbLen) { + word = parseBase(number, i, i + limbLen, base); + + this.imuln(limbPow); + if (this.words[0] + word < 0x4000000) { + this.words[0] += word; + } else { + this._iaddn(word); + } + } + + if (mod !== 0) { + var pow = 1; + word = parseBase(number, i, number.length, base); + + for (i = 0; i < mod; i++) { + pow *= base; + } + + this.imuln(pow); + if (this.words[0] + word < 0x4000000) { + this.words[0] += word; + } else { + this._iaddn(word); + } + } + }; + + BN.prototype.copy = function copy (dest) { + dest.words = new Array(this.length); + for (var i = 0; i < this.length; i++) { + dest.words[i] = this.words[i]; + } + dest.length = this.length; + dest.negative = this.negative; + dest.red = this.red; + }; + + BN.prototype.clone = function clone () { + var r = new BN(null); + this.copy(r); + return r; + }; + + BN.prototype._expand = function _expand (size) { + while (this.length < size) { + this.words[this.length++] = 0; + } + return this; + }; + + // Remove leading `0` from `this` + BN.prototype.strip = function strip () { + while (this.length > 1 && this.words[this.length - 1] === 0) { + this.length--; + } + return this._normSign(); + }; + + BN.prototype._normSign = function _normSign () { + // -0 = 0 + if (this.length === 1 && this.words[0] === 0) { + this.negative = 0; + } + return this; + }; + + BN.prototype.inspect = function inspect () { + return (this.red ? ''; + }; + + /* + + var zeros = []; + var groupSizes = []; + var groupBases = []; + + var s = ''; + var i = -1; + while (++i < BN.wordSize) { + zeros[i] = s; + s += '0'; + } + groupSizes[0] = 0; + groupSizes[1] = 0; + groupBases[0] = 0; + groupBases[1] = 0; + var base = 2 - 1; + while (++base < 36 + 1) { + var groupSize = 0; + var groupBase = 1; + while (groupBase < (1 << BN.wordSize) / base) { + groupBase *= base; + groupSize += 1; + } + groupSizes[base] = groupSize; + groupBases[base] = groupBase; + } + + */ + + var zeros = [ + '', + '0', + '00', + '000', + '0000', + '00000', + '000000', + '0000000', + '00000000', + '000000000', + '0000000000', + '00000000000', + '000000000000', + '0000000000000', + '00000000000000', + '000000000000000', + '0000000000000000', + '00000000000000000', + '000000000000000000', + '0000000000000000000', + '00000000000000000000', + '000000000000000000000', + '0000000000000000000000', + '00000000000000000000000', + '000000000000000000000000', + '0000000000000000000000000' + ]; + + var groupSizes = [ + 0, 0, + 25, 16, 12, 11, 10, 9, 8, + 8, 7, 7, 7, 7, 6, 6, + 6, 6, 6, 6, 6, 5, 5, + 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5 + ]; + + var groupBases = [ + 0, 0, + 33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216, + 43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625, + 16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632, + 6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149, + 24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176 + ]; + + BN.prototype.toString = function toString (base, padding) { + base = base || 10; + padding = padding | 0 || 1; + + var out; + if (base === 16 || base === 'hex') { + out = ''; + var off = 0; + var carry = 0; + for (var i = 0; i < this.length; i++) { + var w = this.words[i]; + var word = (((w << off) | carry) & 0xffffff).toString(16); + carry = (w >>> (24 - off)) & 0xffffff; + if (carry !== 0 || i !== this.length - 1) { + out = zeros[6 - word.length] + word + out; + } else { + out = word + out; + } + off += 2; + if (off >= 26) { + off -= 26; + i--; + } + } + if (carry !== 0) { + out = carry.toString(16) + out; + } + while (out.length % padding !== 0) { + out = '0' + out; + } + if (this.negative !== 0) { + out = '-' + out; + } + return out; + } + + if (base === (base | 0) && base >= 2 && base <= 36) { + // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base)); + var groupSize = groupSizes[base]; + // var groupBase = Math.pow(base, groupSize); + var groupBase = groupBases[base]; + out = ''; + var c = this.clone(); + c.negative = 0; + while (!c.isZero()) { + var r = c.modn(groupBase).toString(base); + c = c.idivn(groupBase); + + if (!c.isZero()) { + out = zeros[groupSize - r.length] + r + out; + } else { + out = r + out; + } + } + if (this.isZero()) { + out = '0' + out; + } + while (out.length % padding !== 0) { + out = '0' + out; + } + if (this.negative !== 0) { + out = '-' + out; + } + return out; + } + + assert(false, 'Base should be between 2 and 36'); + }; + + BN.prototype.toNumber = function toNumber () { + var ret = this.words[0]; + if (this.length === 2) { + ret += this.words[1] * 0x4000000; + } else if (this.length === 3 && this.words[2] === 0x01) { + // NOTE: at this stage it is known that the top bit is set + ret += 0x10000000000000 + (this.words[1] * 0x4000000); + } else if (this.length > 2) { + assert(false, 'Number can only safely store up to 53 bits'); + } + return (this.negative !== 0) ? -ret : ret; + }; + + BN.prototype.toJSON = function toJSON () { + return this.toString(16); + }; + + BN.prototype.toBuffer = function toBuffer (endian, length) { + assert(typeof Buffer !== 'undefined'); + return this.toArrayLike(Buffer, endian, length); + }; + + BN.prototype.toArray = function toArray (endian, length) { + return this.toArrayLike(Array, endian, length); + }; + + BN.prototype.toArrayLike = function toArrayLike (ArrayType, endian, length) { + var byteLength = this.byteLength(); + var reqLength = length || Math.max(1, byteLength); + assert(byteLength <= reqLength, 'byte array longer than desired length'); + assert(reqLength > 0, 'Requested array length <= 0'); + + this.strip(); + var littleEndian = endian === 'le'; + var res = new ArrayType(reqLength); + + var b, i; + var q = this.clone(); + if (!littleEndian) { + // Assume big-endian + for (i = 0; i < reqLength - byteLength; i++) { + res[i] = 0; + } + + for (i = 0; !q.isZero(); i++) { + b = q.andln(0xff); + q.iushrn(8); + + res[reqLength - i - 1] = b; + } + } else { + for (i = 0; !q.isZero(); i++) { + b = q.andln(0xff); + q.iushrn(8); + + res[i] = b; + } + + for (; i < reqLength; i++) { + res[i] = 0; + } + } + + return res; + }; + + if (Math.clz32) { + BN.prototype._countBits = function _countBits (w) { + return 32 - Math.clz32(w); + }; + } else { + BN.prototype._countBits = function _countBits (w) { + var t = w; + var r = 0; + if (t >= 0x1000) { + r += 13; + t >>>= 13; + } + if (t >= 0x40) { + r += 7; + t >>>= 7; + } + if (t >= 0x8) { + r += 4; + t >>>= 4; + } + if (t >= 0x02) { + r += 2; + t >>>= 2; + } + return r + t; + }; + } + + BN.prototype._zeroBits = function _zeroBits (w) { + // Short-cut + if (w === 0) return 26; + + var t = w; + var r = 0; + if ((t & 0x1fff) === 0) { + r += 13; + t >>>= 13; + } + if ((t & 0x7f) === 0) { + r += 7; + t >>>= 7; + } + if ((t & 0xf) === 0) { + r += 4; + t >>>= 4; + } + if ((t & 0x3) === 0) { + r += 2; + t >>>= 2; + } + if ((t & 0x1) === 0) { + r++; + } + return r; + }; + + // Return number of used bits in a BN + BN.prototype.bitLength = function bitLength () { + var w = this.words[this.length - 1]; + var hi = this._countBits(w); + return (this.length - 1) * 26 + hi; + }; + + function toBitArray (num) { + var w = new Array(num.bitLength()); + + for (var bit = 0; bit < w.length; bit++) { + var off = (bit / 26) | 0; + var wbit = bit % 26; + + w[bit] = (num.words[off] & (1 << wbit)) >>> wbit; + } + + return w; + } + + // Number of trailing zero bits + BN.prototype.zeroBits = function zeroBits () { + if (this.isZero()) return 0; + + var r = 0; + for (var i = 0; i < this.length; i++) { + var b = this._zeroBits(this.words[i]); + r += b; + if (b !== 26) break; + } + return r; + }; + + BN.prototype.byteLength = function byteLength () { + return Math.ceil(this.bitLength() / 8); + }; + + BN.prototype.toTwos = function toTwos (width) { + if (this.negative !== 0) { + return this.abs().inotn(width).iaddn(1); + } + return this.clone(); + }; + + BN.prototype.fromTwos = function fromTwos (width) { + if (this.testn(width - 1)) { + return this.notn(width).iaddn(1).ineg(); + } + return this.clone(); + }; + + BN.prototype.isNeg = function isNeg () { + return this.negative !== 0; + }; + + // Return negative clone of `this` + BN.prototype.neg = function neg () { + return this.clone().ineg(); + }; + + BN.prototype.ineg = function ineg () { + if (!this.isZero()) { + this.negative ^= 1; + } + + return this; + }; + + // Or `num` with `this` in-place + BN.prototype.iuor = function iuor (num) { + while (this.length < num.length) { + this.words[this.length++] = 0; + } + + for (var i = 0; i < num.length; i++) { + this.words[i] = this.words[i] | num.words[i]; + } + + return this.strip(); + }; + + BN.prototype.ior = function ior (num) { + assert((this.negative | num.negative) === 0); + return this.iuor(num); + }; + + // Or `num` with `this` + BN.prototype.or = function or (num) { + if (this.length > num.length) return this.clone().ior(num); + return num.clone().ior(this); + }; + + BN.prototype.uor = function uor (num) { + if (this.length > num.length) return this.clone().iuor(num); + return num.clone().iuor(this); + }; + + // And `num` with `this` in-place + BN.prototype.iuand = function iuand (num) { + // b = min-length(num, this) + var b; + if (this.length > num.length) { + b = num; + } else { + b = this; + } + + for (var i = 0; i < b.length; i++) { + this.words[i] = this.words[i] & num.words[i]; + } + + this.length = b.length; + + return this.strip(); + }; + + BN.prototype.iand = function iand (num) { + assert((this.negative | num.negative) === 0); + return this.iuand(num); + }; + + // And `num` with `this` + BN.prototype.and = function and (num) { + if (this.length > num.length) return this.clone().iand(num); + return num.clone().iand(this); + }; + + BN.prototype.uand = function uand (num) { + if (this.length > num.length) return this.clone().iuand(num); + return num.clone().iuand(this); + }; + + // Xor `num` with `this` in-place + BN.prototype.iuxor = function iuxor (num) { + // a.length > b.length + var a; + var b; + if (this.length > num.length) { + a = this; + b = num; + } else { + a = num; + b = this; + } + + for (var i = 0; i < b.length; i++) { + this.words[i] = a.words[i] ^ b.words[i]; + } + + if (this !== a) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } + + this.length = a.length; + + return this.strip(); + }; + + BN.prototype.ixor = function ixor (num) { + assert((this.negative | num.negative) === 0); + return this.iuxor(num); + }; + + // Xor `num` with `this` + BN.prototype.xor = function xor (num) { + if (this.length > num.length) return this.clone().ixor(num); + return num.clone().ixor(this); + }; + + BN.prototype.uxor = function uxor (num) { + if (this.length > num.length) return this.clone().iuxor(num); + return num.clone().iuxor(this); + }; + + // Not ``this`` with ``width`` bitwidth + BN.prototype.inotn = function inotn (width) { + assert(typeof width === 'number' && width >= 0); + + var bytesNeeded = Math.ceil(width / 26) | 0; + var bitsLeft = width % 26; + + // Extend the buffer with leading zeroes + this._expand(bytesNeeded); + + if (bitsLeft > 0) { + bytesNeeded--; + } + + // Handle complete words + for (var i = 0; i < bytesNeeded; i++) { + this.words[i] = ~this.words[i] & 0x3ffffff; + } + + // Handle the residue + if (bitsLeft > 0) { + this.words[i] = ~this.words[i] & (0x3ffffff >> (26 - bitsLeft)); + } + + // And remove leading zeroes + return this.strip(); + }; + + BN.prototype.notn = function notn (width) { + return this.clone().inotn(width); + }; + + // Set `bit` of `this` + BN.prototype.setn = function setn (bit, val) { + assert(typeof bit === 'number' && bit >= 0); + + var off = (bit / 26) | 0; + var wbit = bit % 26; + + this._expand(off + 1); + + if (val) { + this.words[off] = this.words[off] | (1 << wbit); + } else { + this.words[off] = this.words[off] & ~(1 << wbit); + } + + return this.strip(); + }; + + // Add `num` to `this` in-place + BN.prototype.iadd = function iadd (num) { + var r; + + // negative + positive + if (this.negative !== 0 && num.negative === 0) { + this.negative = 0; + r = this.isub(num); + this.negative ^= 1; + return this._normSign(); + + // positive + negative + } else if (this.negative === 0 && num.negative !== 0) { + num.negative = 0; + r = this.isub(num); + num.negative = 1; + return r._normSign(); + } + + // a.length > b.length + var a, b; + if (this.length > num.length) { + a = this; + b = num; + } else { + a = num; + b = this; + } + + var carry = 0; + for (var i = 0; i < b.length; i++) { + r = (a.words[i] | 0) + (b.words[i] | 0) + carry; + this.words[i] = r & 0x3ffffff; + carry = r >>> 26; + } + for (; carry !== 0 && i < a.length; i++) { + r = (a.words[i] | 0) + carry; + this.words[i] = r & 0x3ffffff; + carry = r >>> 26; + } + + this.length = a.length; + if (carry !== 0) { + this.words[this.length] = carry; + this.length++; + // Copy the rest of the words + } else if (a !== this) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } + + return this; + }; + + // Add `num` to `this` + BN.prototype.add = function add (num) { + var res; + if (num.negative !== 0 && this.negative === 0) { + num.negative = 0; + res = this.sub(num); + num.negative ^= 1; + return res; + } else if (num.negative === 0 && this.negative !== 0) { + this.negative = 0; + res = num.sub(this); + this.negative = 1; + return res; + } + + if (this.length > num.length) return this.clone().iadd(num); + + return num.clone().iadd(this); + }; + + // Subtract `num` from `this` in-place + BN.prototype.isub = function isub (num) { + // this - (-num) = this + num + if (num.negative !== 0) { + num.negative = 0; + var r = this.iadd(num); + num.negative = 1; + return r._normSign(); + + // -this - num = -(this + num) + } else if (this.negative !== 0) { + this.negative = 0; + this.iadd(num); + this.negative = 1; + return this._normSign(); + } + + // At this point both numbers are positive + var cmp = this.cmp(num); + + // Optimization - zeroify + if (cmp === 0) { + this.negative = 0; + this.length = 1; + this.words[0] = 0; + return this; + } + + // a > b + var a, b; + if (cmp > 0) { + a = this; + b = num; + } else { + a = num; + b = this; + } + + var carry = 0; + for (var i = 0; i < b.length; i++) { + r = (a.words[i] | 0) - (b.words[i] | 0) + carry; + carry = r >> 26; + this.words[i] = r & 0x3ffffff; + } + for (; carry !== 0 && i < a.length; i++) { + r = (a.words[i] | 0) + carry; + carry = r >> 26; + this.words[i] = r & 0x3ffffff; + } + + // Copy rest of the words + if (carry === 0 && i < a.length && a !== this) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } + + this.length = Math.max(this.length, i); + + if (a !== this) { + this.negative = 1; + } + + return this.strip(); + }; + + // Subtract `num` from `this` + BN.prototype.sub = function sub (num) { + return this.clone().isub(num); + }; + + function smallMulTo (self, num, out) { + out.negative = num.negative ^ self.negative; + var len = (self.length + num.length) | 0; + out.length = len; + len = (len - 1) | 0; + + // Peel one iteration (compiler can't do it, because of code complexity) + var a = self.words[0] | 0; + var b = num.words[0] | 0; + var r = a * b; + + var lo = r & 0x3ffffff; + var carry = (r / 0x4000000) | 0; + out.words[0] = lo; + + for (var k = 1; k < len; k++) { + // Sum all words with the same `i + j = k` and accumulate `ncarry`, + // note that ncarry could be >= 0x3ffffff + var ncarry = carry >>> 26; + var rword = carry & 0x3ffffff; + var maxJ = Math.min(k, num.length - 1); + for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { + var i = (k - j) | 0; + a = self.words[i] | 0; + b = num.words[j] | 0; + r = a * b + rword; + ncarry += (r / 0x4000000) | 0; + rword = r & 0x3ffffff; + } + out.words[k] = rword | 0; + carry = ncarry | 0; + } + if (carry !== 0) { + out.words[k] = carry | 0; + } else { + out.length--; + } + + return out.strip(); + } + + // TODO(indutny): it may be reasonable to omit it for users who don't need + // to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit + // multiplication (like elliptic secp256k1). + var comb10MulTo = function comb10MulTo (self, num, out) { + var a = self.words; + var b = num.words; + var o = out.words; + var c = 0; + var lo; + var mid; + var hi; + var a0 = a[0] | 0; + var al0 = a0 & 0x1fff; + var ah0 = a0 >>> 13; + var a1 = a[1] | 0; + var al1 = a1 & 0x1fff; + var ah1 = a1 >>> 13; + var a2 = a[2] | 0; + var al2 = a2 & 0x1fff; + var ah2 = a2 >>> 13; + var a3 = a[3] | 0; + var al3 = a3 & 0x1fff; + var ah3 = a3 >>> 13; + var a4 = a[4] | 0; + var al4 = a4 & 0x1fff; + var ah4 = a4 >>> 13; + var a5 = a[5] | 0; + var al5 = a5 & 0x1fff; + var ah5 = a5 >>> 13; + var a6 = a[6] | 0; + var al6 = a6 & 0x1fff; + var ah6 = a6 >>> 13; + var a7 = a[7] | 0; + var al7 = a7 & 0x1fff; + var ah7 = a7 >>> 13; + var a8 = a[8] | 0; + var al8 = a8 & 0x1fff; + var ah8 = a8 >>> 13; + var a9 = a[9] | 0; + var al9 = a9 & 0x1fff; + var ah9 = a9 >>> 13; + var b0 = b[0] | 0; + var bl0 = b0 & 0x1fff; + var bh0 = b0 >>> 13; + var b1 = b[1] | 0; + var bl1 = b1 & 0x1fff; + var bh1 = b1 >>> 13; + var b2 = b[2] | 0; + var bl2 = b2 & 0x1fff; + var bh2 = b2 >>> 13; + var b3 = b[3] | 0; + var bl3 = b3 & 0x1fff; + var bh3 = b3 >>> 13; + var b4 = b[4] | 0; + var bl4 = b4 & 0x1fff; + var bh4 = b4 >>> 13; + var b5 = b[5] | 0; + var bl5 = b5 & 0x1fff; + var bh5 = b5 >>> 13; + var b6 = b[6] | 0; + var bl6 = b6 & 0x1fff; + var bh6 = b6 >>> 13; + var b7 = b[7] | 0; + var bl7 = b7 & 0x1fff; + var bh7 = b7 >>> 13; + var b8 = b[8] | 0; + var bl8 = b8 & 0x1fff; + var bh8 = b8 >>> 13; + var b9 = b[9] | 0; + var bl9 = b9 & 0x1fff; + var bh9 = b9 >>> 13; + + out.negative = self.negative ^ num.negative; + out.length = 19; + /* k = 0 */ + lo = Math.imul(al0, bl0); + mid = Math.imul(al0, bh0); + mid = (mid + Math.imul(ah0, bl0)) | 0; + hi = Math.imul(ah0, bh0); + var w0 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w0 >>> 26)) | 0; + w0 &= 0x3ffffff; + /* k = 1 */ + lo = Math.imul(al1, bl0); + mid = Math.imul(al1, bh0); + mid = (mid + Math.imul(ah1, bl0)) | 0; + hi = Math.imul(ah1, bh0); + lo = (lo + Math.imul(al0, bl1)) | 0; + mid = (mid + Math.imul(al0, bh1)) | 0; + mid = (mid + Math.imul(ah0, bl1)) | 0; + hi = (hi + Math.imul(ah0, bh1)) | 0; + var w1 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w1 >>> 26)) | 0; + w1 &= 0x3ffffff; + /* k = 2 */ + lo = Math.imul(al2, bl0); + mid = Math.imul(al2, bh0); + mid = (mid + Math.imul(ah2, bl0)) | 0; + hi = Math.imul(ah2, bh0); + lo = (lo + Math.imul(al1, bl1)) | 0; + mid = (mid + Math.imul(al1, bh1)) | 0; + mid = (mid + Math.imul(ah1, bl1)) | 0; + hi = (hi + Math.imul(ah1, bh1)) | 0; + lo = (lo + Math.imul(al0, bl2)) | 0; + mid = (mid + Math.imul(al0, bh2)) | 0; + mid = (mid + Math.imul(ah0, bl2)) | 0; + hi = (hi + Math.imul(ah0, bh2)) | 0; + var w2 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w2 >>> 26)) | 0; + w2 &= 0x3ffffff; + /* k = 3 */ + lo = Math.imul(al3, bl0); + mid = Math.imul(al3, bh0); + mid = (mid + Math.imul(ah3, bl0)) | 0; + hi = Math.imul(ah3, bh0); + lo = (lo + Math.imul(al2, bl1)) | 0; + mid = (mid + Math.imul(al2, bh1)) | 0; + mid = (mid + Math.imul(ah2, bl1)) | 0; + hi = (hi + Math.imul(ah2, bh1)) | 0; + lo = (lo + Math.imul(al1, bl2)) | 0; + mid = (mid + Math.imul(al1, bh2)) | 0; + mid = (mid + Math.imul(ah1, bl2)) | 0; + hi = (hi + Math.imul(ah1, bh2)) | 0; + lo = (lo + Math.imul(al0, bl3)) | 0; + mid = (mid + Math.imul(al0, bh3)) | 0; + mid = (mid + Math.imul(ah0, bl3)) | 0; + hi = (hi + Math.imul(ah0, bh3)) | 0; + var w3 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w3 >>> 26)) | 0; + w3 &= 0x3ffffff; + /* k = 4 */ + lo = Math.imul(al4, bl0); + mid = Math.imul(al4, bh0); + mid = (mid + Math.imul(ah4, bl0)) | 0; + hi = Math.imul(ah4, bh0); + lo = (lo + Math.imul(al3, bl1)) | 0; + mid = (mid + Math.imul(al3, bh1)) | 0; + mid = (mid + Math.imul(ah3, bl1)) | 0; + hi = (hi + Math.imul(ah3, bh1)) | 0; + lo = (lo + Math.imul(al2, bl2)) | 0; + mid = (mid + Math.imul(al2, bh2)) | 0; + mid = (mid + Math.imul(ah2, bl2)) | 0; + hi = (hi + Math.imul(ah2, bh2)) | 0; + lo = (lo + Math.imul(al1, bl3)) | 0; + mid = (mid + Math.imul(al1, bh3)) | 0; + mid = (mid + Math.imul(ah1, bl3)) | 0; + hi = (hi + Math.imul(ah1, bh3)) | 0; + lo = (lo + Math.imul(al0, bl4)) | 0; + mid = (mid + Math.imul(al0, bh4)) | 0; + mid = (mid + Math.imul(ah0, bl4)) | 0; + hi = (hi + Math.imul(ah0, bh4)) | 0; + var w4 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w4 >>> 26)) | 0; + w4 &= 0x3ffffff; + /* k = 5 */ + lo = Math.imul(al5, bl0); + mid = Math.imul(al5, bh0); + mid = (mid + Math.imul(ah5, bl0)) | 0; + hi = Math.imul(ah5, bh0); + lo = (lo + Math.imul(al4, bl1)) | 0; + mid = (mid + Math.imul(al4, bh1)) | 0; + mid = (mid + Math.imul(ah4, bl1)) | 0; + hi = (hi + Math.imul(ah4, bh1)) | 0; + lo = (lo + Math.imul(al3, bl2)) | 0; + mid = (mid + Math.imul(al3, bh2)) | 0; + mid = (mid + Math.imul(ah3, bl2)) | 0; + hi = (hi + Math.imul(ah3, bh2)) | 0; + lo = (lo + Math.imul(al2, bl3)) | 0; + mid = (mid + Math.imul(al2, bh3)) | 0; + mid = (mid + Math.imul(ah2, bl3)) | 0; + hi = (hi + Math.imul(ah2, bh3)) | 0; + lo = (lo + Math.imul(al1, bl4)) | 0; + mid = (mid + Math.imul(al1, bh4)) | 0; + mid = (mid + Math.imul(ah1, bl4)) | 0; + hi = (hi + Math.imul(ah1, bh4)) | 0; + lo = (lo + Math.imul(al0, bl5)) | 0; + mid = (mid + Math.imul(al0, bh5)) | 0; + mid = (mid + Math.imul(ah0, bl5)) | 0; + hi = (hi + Math.imul(ah0, bh5)) | 0; + var w5 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w5 >>> 26)) | 0; + w5 &= 0x3ffffff; + /* k = 6 */ + lo = Math.imul(al6, bl0); + mid = Math.imul(al6, bh0); + mid = (mid + Math.imul(ah6, bl0)) | 0; + hi = Math.imul(ah6, bh0); + lo = (lo + Math.imul(al5, bl1)) | 0; + mid = (mid + Math.imul(al5, bh1)) | 0; + mid = (mid + Math.imul(ah5, bl1)) | 0; + hi = (hi + Math.imul(ah5, bh1)) | 0; + lo = (lo + Math.imul(al4, bl2)) | 0; + mid = (mid + Math.imul(al4, bh2)) | 0; + mid = (mid + Math.imul(ah4, bl2)) | 0; + hi = (hi + Math.imul(ah4, bh2)) | 0; + lo = (lo + Math.imul(al3, bl3)) | 0; + mid = (mid + Math.imul(al3, bh3)) | 0; + mid = (mid + Math.imul(ah3, bl3)) | 0; + hi = (hi + Math.imul(ah3, bh3)) | 0; + lo = (lo + Math.imul(al2, bl4)) | 0; + mid = (mid + Math.imul(al2, bh4)) | 0; + mid = (mid + Math.imul(ah2, bl4)) | 0; + hi = (hi + Math.imul(ah2, bh4)) | 0; + lo = (lo + Math.imul(al1, bl5)) | 0; + mid = (mid + Math.imul(al1, bh5)) | 0; + mid = (mid + Math.imul(ah1, bl5)) | 0; + hi = (hi + Math.imul(ah1, bh5)) | 0; + lo = (lo + Math.imul(al0, bl6)) | 0; + mid = (mid + Math.imul(al0, bh6)) | 0; + mid = (mid + Math.imul(ah0, bl6)) | 0; + hi = (hi + Math.imul(ah0, bh6)) | 0; + var w6 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w6 >>> 26)) | 0; + w6 &= 0x3ffffff; + /* k = 7 */ + lo = Math.imul(al7, bl0); + mid = Math.imul(al7, bh0); + mid = (mid + Math.imul(ah7, bl0)) | 0; + hi = Math.imul(ah7, bh0); + lo = (lo + Math.imul(al6, bl1)) | 0; + mid = (mid + Math.imul(al6, bh1)) | 0; + mid = (mid + Math.imul(ah6, bl1)) | 0; + hi = (hi + Math.imul(ah6, bh1)) | 0; + lo = (lo + Math.imul(al5, bl2)) | 0; + mid = (mid + Math.imul(al5, bh2)) | 0; + mid = (mid + Math.imul(ah5, bl2)) | 0; + hi = (hi + Math.imul(ah5, bh2)) | 0; + lo = (lo + Math.imul(al4, bl3)) | 0; + mid = (mid + Math.imul(al4, bh3)) | 0; + mid = (mid + Math.imul(ah4, bl3)) | 0; + hi = (hi + Math.imul(ah4, bh3)) | 0; + lo = (lo + Math.imul(al3, bl4)) | 0; + mid = (mid + Math.imul(al3, bh4)) | 0; + mid = (mid + Math.imul(ah3, bl4)) | 0; + hi = (hi + Math.imul(ah3, bh4)) | 0; + lo = (lo + Math.imul(al2, bl5)) | 0; + mid = (mid + Math.imul(al2, bh5)) | 0; + mid = (mid + Math.imul(ah2, bl5)) | 0; + hi = (hi + Math.imul(ah2, bh5)) | 0; + lo = (lo + Math.imul(al1, bl6)) | 0; + mid = (mid + Math.imul(al1, bh6)) | 0; + mid = (mid + Math.imul(ah1, bl6)) | 0; + hi = (hi + Math.imul(ah1, bh6)) | 0; + lo = (lo + Math.imul(al0, bl7)) | 0; + mid = (mid + Math.imul(al0, bh7)) | 0; + mid = (mid + Math.imul(ah0, bl7)) | 0; + hi = (hi + Math.imul(ah0, bh7)) | 0; + var w7 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w7 >>> 26)) | 0; + w7 &= 0x3ffffff; + /* k = 8 */ + lo = Math.imul(al8, bl0); + mid = Math.imul(al8, bh0); + mid = (mid + Math.imul(ah8, bl0)) | 0; + hi = Math.imul(ah8, bh0); + lo = (lo + Math.imul(al7, bl1)) | 0; + mid = (mid + Math.imul(al7, bh1)) | 0; + mid = (mid + Math.imul(ah7, bl1)) | 0; + hi = (hi + Math.imul(ah7, bh1)) | 0; + lo = (lo + Math.imul(al6, bl2)) | 0; + mid = (mid + Math.imul(al6, bh2)) | 0; + mid = (mid + Math.imul(ah6, bl2)) | 0; + hi = (hi + Math.imul(ah6, bh2)) | 0; + lo = (lo + Math.imul(al5, bl3)) | 0; + mid = (mid + Math.imul(al5, bh3)) | 0; + mid = (mid + Math.imul(ah5, bl3)) | 0; + hi = (hi + Math.imul(ah5, bh3)) | 0; + lo = (lo + Math.imul(al4, bl4)) | 0; + mid = (mid + Math.imul(al4, bh4)) | 0; + mid = (mid + Math.imul(ah4, bl4)) | 0; + hi = (hi + Math.imul(ah4, bh4)) | 0; + lo = (lo + Math.imul(al3, bl5)) | 0; + mid = (mid + Math.imul(al3, bh5)) | 0; + mid = (mid + Math.imul(ah3, bl5)) | 0; + hi = (hi + Math.imul(ah3, bh5)) | 0; + lo = (lo + Math.imul(al2, bl6)) | 0; + mid = (mid + Math.imul(al2, bh6)) | 0; + mid = (mid + Math.imul(ah2, bl6)) | 0; + hi = (hi + Math.imul(ah2, bh6)) | 0; + lo = (lo + Math.imul(al1, bl7)) | 0; + mid = (mid + Math.imul(al1, bh7)) | 0; + mid = (mid + Math.imul(ah1, bl7)) | 0; + hi = (hi + Math.imul(ah1, bh7)) | 0; + lo = (lo + Math.imul(al0, bl8)) | 0; + mid = (mid + Math.imul(al0, bh8)) | 0; + mid = (mid + Math.imul(ah0, bl8)) | 0; + hi = (hi + Math.imul(ah0, bh8)) | 0; + var w8 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w8 >>> 26)) | 0; + w8 &= 0x3ffffff; + /* k = 9 */ + lo = Math.imul(al9, bl0); + mid = Math.imul(al9, bh0); + mid = (mid + Math.imul(ah9, bl0)) | 0; + hi = Math.imul(ah9, bh0); + lo = (lo + Math.imul(al8, bl1)) | 0; + mid = (mid + Math.imul(al8, bh1)) | 0; + mid = (mid + Math.imul(ah8, bl1)) | 0; + hi = (hi + Math.imul(ah8, bh1)) | 0; + lo = (lo + Math.imul(al7, bl2)) | 0; + mid = (mid + Math.imul(al7, bh2)) | 0; + mid = (mid + Math.imul(ah7, bl2)) | 0; + hi = (hi + Math.imul(ah7, bh2)) | 0; + lo = (lo + Math.imul(al6, bl3)) | 0; + mid = (mid + Math.imul(al6, bh3)) | 0; + mid = (mid + Math.imul(ah6, bl3)) | 0; + hi = (hi + Math.imul(ah6, bh3)) | 0; + lo = (lo + Math.imul(al5, bl4)) | 0; + mid = (mid + Math.imul(al5, bh4)) | 0; + mid = (mid + Math.imul(ah5, bl4)) | 0; + hi = (hi + Math.imul(ah5, bh4)) | 0; + lo = (lo + Math.imul(al4, bl5)) | 0; + mid = (mid + Math.imul(al4, bh5)) | 0; + mid = (mid + Math.imul(ah4, bl5)) | 0; + hi = (hi + Math.imul(ah4, bh5)) | 0; + lo = (lo + Math.imul(al3, bl6)) | 0; + mid = (mid + Math.imul(al3, bh6)) | 0; + mid = (mid + Math.imul(ah3, bl6)) | 0; + hi = (hi + Math.imul(ah3, bh6)) | 0; + lo = (lo + Math.imul(al2, bl7)) | 0; + mid = (mid + Math.imul(al2, bh7)) | 0; + mid = (mid + Math.imul(ah2, bl7)) | 0; + hi = (hi + Math.imul(ah2, bh7)) | 0; + lo = (lo + Math.imul(al1, bl8)) | 0; + mid = (mid + Math.imul(al1, bh8)) | 0; + mid = (mid + Math.imul(ah1, bl8)) | 0; + hi = (hi + Math.imul(ah1, bh8)) | 0; + lo = (lo + Math.imul(al0, bl9)) | 0; + mid = (mid + Math.imul(al0, bh9)) | 0; + mid = (mid + Math.imul(ah0, bl9)) | 0; + hi = (hi + Math.imul(ah0, bh9)) | 0; + var w9 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w9 >>> 26)) | 0; + w9 &= 0x3ffffff; + /* k = 10 */ + lo = Math.imul(al9, bl1); + mid = Math.imul(al9, bh1); + mid = (mid + Math.imul(ah9, bl1)) | 0; + hi = Math.imul(ah9, bh1); + lo = (lo + Math.imul(al8, bl2)) | 0; + mid = (mid + Math.imul(al8, bh2)) | 0; + mid = (mid + Math.imul(ah8, bl2)) | 0; + hi = (hi + Math.imul(ah8, bh2)) | 0; + lo = (lo + Math.imul(al7, bl3)) | 0; + mid = (mid + Math.imul(al7, bh3)) | 0; + mid = (mid + Math.imul(ah7, bl3)) | 0; + hi = (hi + Math.imul(ah7, bh3)) | 0; + lo = (lo + Math.imul(al6, bl4)) | 0; + mid = (mid + Math.imul(al6, bh4)) | 0; + mid = (mid + Math.imul(ah6, bl4)) | 0; + hi = (hi + Math.imul(ah6, bh4)) | 0; + lo = (lo + Math.imul(al5, bl5)) | 0; + mid = (mid + Math.imul(al5, bh5)) | 0; + mid = (mid + Math.imul(ah5, bl5)) | 0; + hi = (hi + Math.imul(ah5, bh5)) | 0; + lo = (lo + Math.imul(al4, bl6)) | 0; + mid = (mid + Math.imul(al4, bh6)) | 0; + mid = (mid + Math.imul(ah4, bl6)) | 0; + hi = (hi + Math.imul(ah4, bh6)) | 0; + lo = (lo + Math.imul(al3, bl7)) | 0; + mid = (mid + Math.imul(al3, bh7)) | 0; + mid = (mid + Math.imul(ah3, bl7)) | 0; + hi = (hi + Math.imul(ah3, bh7)) | 0; + lo = (lo + Math.imul(al2, bl8)) | 0; + mid = (mid + Math.imul(al2, bh8)) | 0; + mid = (mid + Math.imul(ah2, bl8)) | 0; + hi = (hi + Math.imul(ah2, bh8)) | 0; + lo = (lo + Math.imul(al1, bl9)) | 0; + mid = (mid + Math.imul(al1, bh9)) | 0; + mid = (mid + Math.imul(ah1, bl9)) | 0; + hi = (hi + Math.imul(ah1, bh9)) | 0; + var w10 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w10 >>> 26)) | 0; + w10 &= 0x3ffffff; + /* k = 11 */ + lo = Math.imul(al9, bl2); + mid = Math.imul(al9, bh2); + mid = (mid + Math.imul(ah9, bl2)) | 0; + hi = Math.imul(ah9, bh2); + lo = (lo + Math.imul(al8, bl3)) | 0; + mid = (mid + Math.imul(al8, bh3)) | 0; + mid = (mid + Math.imul(ah8, bl3)) | 0; + hi = (hi + Math.imul(ah8, bh3)) | 0; + lo = (lo + Math.imul(al7, bl4)) | 0; + mid = (mid + Math.imul(al7, bh4)) | 0; + mid = (mid + Math.imul(ah7, bl4)) | 0; + hi = (hi + Math.imul(ah7, bh4)) | 0; + lo = (lo + Math.imul(al6, bl5)) | 0; + mid = (mid + Math.imul(al6, bh5)) | 0; + mid = (mid + Math.imul(ah6, bl5)) | 0; + hi = (hi + Math.imul(ah6, bh5)) | 0; + lo = (lo + Math.imul(al5, bl6)) | 0; + mid = (mid + Math.imul(al5, bh6)) | 0; + mid = (mid + Math.imul(ah5, bl6)) | 0; + hi = (hi + Math.imul(ah5, bh6)) | 0; + lo = (lo + Math.imul(al4, bl7)) | 0; + mid = (mid + Math.imul(al4, bh7)) | 0; + mid = (mid + Math.imul(ah4, bl7)) | 0; + hi = (hi + Math.imul(ah4, bh7)) | 0; + lo = (lo + Math.imul(al3, bl8)) | 0; + mid = (mid + Math.imul(al3, bh8)) | 0; + mid = (mid + Math.imul(ah3, bl8)) | 0; + hi = (hi + Math.imul(ah3, bh8)) | 0; + lo = (lo + Math.imul(al2, bl9)) | 0; + mid = (mid + Math.imul(al2, bh9)) | 0; + mid = (mid + Math.imul(ah2, bl9)) | 0; + hi = (hi + Math.imul(ah2, bh9)) | 0; + var w11 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w11 >>> 26)) | 0; + w11 &= 0x3ffffff; + /* k = 12 */ + lo = Math.imul(al9, bl3); + mid = Math.imul(al9, bh3); + mid = (mid + Math.imul(ah9, bl3)) | 0; + hi = Math.imul(ah9, bh3); + lo = (lo + Math.imul(al8, bl4)) | 0; + mid = (mid + Math.imul(al8, bh4)) | 0; + mid = (mid + Math.imul(ah8, bl4)) | 0; + hi = (hi + Math.imul(ah8, bh4)) | 0; + lo = (lo + Math.imul(al7, bl5)) | 0; + mid = (mid + Math.imul(al7, bh5)) | 0; + mid = (mid + Math.imul(ah7, bl5)) | 0; + hi = (hi + Math.imul(ah7, bh5)) | 0; + lo = (lo + Math.imul(al6, bl6)) | 0; + mid = (mid + Math.imul(al6, bh6)) | 0; + mid = (mid + Math.imul(ah6, bl6)) | 0; + hi = (hi + Math.imul(ah6, bh6)) | 0; + lo = (lo + Math.imul(al5, bl7)) | 0; + mid = (mid + Math.imul(al5, bh7)) | 0; + mid = (mid + Math.imul(ah5, bl7)) | 0; + hi = (hi + Math.imul(ah5, bh7)) | 0; + lo = (lo + Math.imul(al4, bl8)) | 0; + mid = (mid + Math.imul(al4, bh8)) | 0; + mid = (mid + Math.imul(ah4, bl8)) | 0; + hi = (hi + Math.imul(ah4, bh8)) | 0; + lo = (lo + Math.imul(al3, bl9)) | 0; + mid = (mid + Math.imul(al3, bh9)) | 0; + mid = (mid + Math.imul(ah3, bl9)) | 0; + hi = (hi + Math.imul(ah3, bh9)) | 0; + var w12 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w12 >>> 26)) | 0; + w12 &= 0x3ffffff; + /* k = 13 */ + lo = Math.imul(al9, bl4); + mid = Math.imul(al9, bh4); + mid = (mid + Math.imul(ah9, bl4)) | 0; + hi = Math.imul(ah9, bh4); + lo = (lo + Math.imul(al8, bl5)) | 0; + mid = (mid + Math.imul(al8, bh5)) | 0; + mid = (mid + Math.imul(ah8, bl5)) | 0; + hi = (hi + Math.imul(ah8, bh5)) | 0; + lo = (lo + Math.imul(al7, bl6)) | 0; + mid = (mid + Math.imul(al7, bh6)) | 0; + mid = (mid + Math.imul(ah7, bl6)) | 0; + hi = (hi + Math.imul(ah7, bh6)) | 0; + lo = (lo + Math.imul(al6, bl7)) | 0; + mid = (mid + Math.imul(al6, bh7)) | 0; + mid = (mid + Math.imul(ah6, bl7)) | 0; + hi = (hi + Math.imul(ah6, bh7)) | 0; + lo = (lo + Math.imul(al5, bl8)) | 0; + mid = (mid + Math.imul(al5, bh8)) | 0; + mid = (mid + Math.imul(ah5, bl8)) | 0; + hi = (hi + Math.imul(ah5, bh8)) | 0; + lo = (lo + Math.imul(al4, bl9)) | 0; + mid = (mid + Math.imul(al4, bh9)) | 0; + mid = (mid + Math.imul(ah4, bl9)) | 0; + hi = (hi + Math.imul(ah4, bh9)) | 0; + var w13 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w13 >>> 26)) | 0; + w13 &= 0x3ffffff; + /* k = 14 */ + lo = Math.imul(al9, bl5); + mid = Math.imul(al9, bh5); + mid = (mid + Math.imul(ah9, bl5)) | 0; + hi = Math.imul(ah9, bh5); + lo = (lo + Math.imul(al8, bl6)) | 0; + mid = (mid + Math.imul(al8, bh6)) | 0; + mid = (mid + Math.imul(ah8, bl6)) | 0; + hi = (hi + Math.imul(ah8, bh6)) | 0; + lo = (lo + Math.imul(al7, bl7)) | 0; + mid = (mid + Math.imul(al7, bh7)) | 0; + mid = (mid + Math.imul(ah7, bl7)) | 0; + hi = (hi + Math.imul(ah7, bh7)) | 0; + lo = (lo + Math.imul(al6, bl8)) | 0; + mid = (mid + Math.imul(al6, bh8)) | 0; + mid = (mid + Math.imul(ah6, bl8)) | 0; + hi = (hi + Math.imul(ah6, bh8)) | 0; + lo = (lo + Math.imul(al5, bl9)) | 0; + mid = (mid + Math.imul(al5, bh9)) | 0; + mid = (mid + Math.imul(ah5, bl9)) | 0; + hi = (hi + Math.imul(ah5, bh9)) | 0; + var w14 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w14 >>> 26)) | 0; + w14 &= 0x3ffffff; + /* k = 15 */ + lo = Math.imul(al9, bl6); + mid = Math.imul(al9, bh6); + mid = (mid + Math.imul(ah9, bl6)) | 0; + hi = Math.imul(ah9, bh6); + lo = (lo + Math.imul(al8, bl7)) | 0; + mid = (mid + Math.imul(al8, bh7)) | 0; + mid = (mid + Math.imul(ah8, bl7)) | 0; + hi = (hi + Math.imul(ah8, bh7)) | 0; + lo = (lo + Math.imul(al7, bl8)) | 0; + mid = (mid + Math.imul(al7, bh8)) | 0; + mid = (mid + Math.imul(ah7, bl8)) | 0; + hi = (hi + Math.imul(ah7, bh8)) | 0; + lo = (lo + Math.imul(al6, bl9)) | 0; + mid = (mid + Math.imul(al6, bh9)) | 0; + mid = (mid + Math.imul(ah6, bl9)) | 0; + hi = (hi + Math.imul(ah6, bh9)) | 0; + var w15 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w15 >>> 26)) | 0; + w15 &= 0x3ffffff; + /* k = 16 */ + lo = Math.imul(al9, bl7); + mid = Math.imul(al9, bh7); + mid = (mid + Math.imul(ah9, bl7)) | 0; + hi = Math.imul(ah9, bh7); + lo = (lo + Math.imul(al8, bl8)) | 0; + mid = (mid + Math.imul(al8, bh8)) | 0; + mid = (mid + Math.imul(ah8, bl8)) | 0; + hi = (hi + Math.imul(ah8, bh8)) | 0; + lo = (lo + Math.imul(al7, bl9)) | 0; + mid = (mid + Math.imul(al7, bh9)) | 0; + mid = (mid + Math.imul(ah7, bl9)) | 0; + hi = (hi + Math.imul(ah7, bh9)) | 0; + var w16 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w16 >>> 26)) | 0; + w16 &= 0x3ffffff; + /* k = 17 */ + lo = Math.imul(al9, bl8); + mid = Math.imul(al9, bh8); + mid = (mid + Math.imul(ah9, bl8)) | 0; + hi = Math.imul(ah9, bh8); + lo = (lo + Math.imul(al8, bl9)) | 0; + mid = (mid + Math.imul(al8, bh9)) | 0; + mid = (mid + Math.imul(ah8, bl9)) | 0; + hi = (hi + Math.imul(ah8, bh9)) | 0; + var w17 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w17 >>> 26)) | 0; + w17 &= 0x3ffffff; + /* k = 18 */ + lo = Math.imul(al9, bl9); + mid = Math.imul(al9, bh9); + mid = (mid + Math.imul(ah9, bl9)) | 0; + hi = Math.imul(ah9, bh9); + var w18 = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0; + c = (((hi + (mid >>> 13)) | 0) + (w18 >>> 26)) | 0; + w18 &= 0x3ffffff; + o[0] = w0; + o[1] = w1; + o[2] = w2; + o[3] = w3; + o[4] = w4; + o[5] = w5; + o[6] = w6; + o[7] = w7; + o[8] = w8; + o[9] = w9; + o[10] = w10; + o[11] = w11; + o[12] = w12; + o[13] = w13; + o[14] = w14; + o[15] = w15; + o[16] = w16; + o[17] = w17; + o[18] = w18; + if (c !== 0) { + o[19] = c; + out.length++; + } + return out; + }; + + // Polyfill comb + if (!Math.imul) { + comb10MulTo = smallMulTo; + } + + function bigMulTo (self, num, out) { + out.negative = num.negative ^ self.negative; + out.length = self.length + num.length; + + var carry = 0; + var hncarry = 0; + for (var k = 0; k < out.length - 1; k++) { + // Sum all words with the same `i + j = k` and accumulate `ncarry`, + // note that ncarry could be >= 0x3ffffff + var ncarry = hncarry; + hncarry = 0; + var rword = carry & 0x3ffffff; + var maxJ = Math.min(k, num.length - 1); + for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { + var i = k - j; + var a = self.words[i] | 0; + var b = num.words[j] | 0; + var r = a * b; + + var lo = r & 0x3ffffff; + ncarry = (ncarry + ((r / 0x4000000) | 0)) | 0; + lo = (lo + rword) | 0; + rword = lo & 0x3ffffff; + ncarry = (ncarry + (lo >>> 26)) | 0; + + hncarry += ncarry >>> 26; + ncarry &= 0x3ffffff; + } + out.words[k] = rword; + carry = ncarry; + ncarry = hncarry; + } + if (carry !== 0) { + out.words[k] = carry; + } else { + out.length--; + } + + return out.strip(); + } + + function jumboMulTo (self, num, out) { + var fftm = new FFTM(); + return fftm.mulp(self, num, out); + } + + BN.prototype.mulTo = function mulTo (num, out) { + var res; + var len = this.length + num.length; + if (this.length === 10 && num.length === 10) { + res = comb10MulTo(this, num, out); + } else if (len < 63) { + res = smallMulTo(this, num, out); + } else if (len < 1024) { + res = bigMulTo(this, num, out); + } else { + res = jumboMulTo(this, num, out); + } + + return res; + }; + + // Cooley-Tukey algorithm for FFT + // slightly revisited to rely on looping instead of recursion + + function FFTM (x, y) { + this.x = x; + this.y = y; + } + + FFTM.prototype.makeRBT = function makeRBT (N) { + var t = new Array(N); + var l = BN.prototype._countBits(N) - 1; + for (var i = 0; i < N; i++) { + t[i] = this.revBin(i, l, N); + } + + return t; + }; + + // Returns binary-reversed representation of `x` + FFTM.prototype.revBin = function revBin (x, l, N) { + if (x === 0 || x === N - 1) return x; + + var rb = 0; + for (var i = 0; i < l; i++) { + rb |= (x & 1) << (l - i - 1); + x >>= 1; + } + + return rb; + }; + + // Performs "tweedling" phase, therefore 'emulating' + // behaviour of the recursive algorithm + FFTM.prototype.permute = function permute (rbt, rws, iws, rtws, itws, N) { + for (var i = 0; i < N; i++) { + rtws[i] = rws[rbt[i]]; + itws[i] = iws[rbt[i]]; + } + }; + + FFTM.prototype.transform = function transform (rws, iws, rtws, itws, N, rbt) { + this.permute(rbt, rws, iws, rtws, itws, N); + + for (var s = 1; s < N; s <<= 1) { + var l = s << 1; + + var rtwdf = Math.cos(2 * Math.PI / l); + var itwdf = Math.sin(2 * Math.PI / l); + + for (var p = 0; p < N; p += l) { + var rtwdf_ = rtwdf; + var itwdf_ = itwdf; + + for (var j = 0; j < s; j++) { + var re = rtws[p + j]; + var ie = itws[p + j]; + + var ro = rtws[p + j + s]; + var io = itws[p + j + s]; + + var rx = rtwdf_ * ro - itwdf_ * io; + + io = rtwdf_ * io + itwdf_ * ro; + ro = rx; + + rtws[p + j] = re + ro; + itws[p + j] = ie + io; + + rtws[p + j + s] = re - ro; + itws[p + j + s] = ie - io; + + /* jshint maxdepth : false */ + if (j !== l) { + rx = rtwdf * rtwdf_ - itwdf * itwdf_; + + itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_; + rtwdf_ = rx; + } + } + } + } + }; + + FFTM.prototype.guessLen13b = function guessLen13b (n, m) { + var N = Math.max(m, n) | 1; + var odd = N & 1; + var i = 0; + for (N = N / 2 | 0; N; N = N >>> 1) { + i++; + } + + return 1 << i + 1 + odd; + }; + + FFTM.prototype.conjugate = function conjugate (rws, iws, N) { + if (N <= 1) return; + + for (var i = 0; i < N / 2; i++) { + var t = rws[i]; + + rws[i] = rws[N - i - 1]; + rws[N - i - 1] = t; + + t = iws[i]; + + iws[i] = -iws[N - i - 1]; + iws[N - i - 1] = -t; + } + }; + + FFTM.prototype.normalize13b = function normalize13b (ws, N) { + var carry = 0; + for (var i = 0; i < N / 2; i++) { + var w = Math.round(ws[2 * i + 1] / N) * 0x2000 + + Math.round(ws[2 * i] / N) + + carry; + + ws[i] = w & 0x3ffffff; + + if (w < 0x4000000) { + carry = 0; + } else { + carry = w / 0x4000000 | 0; + } + } + + return ws; + }; + + FFTM.prototype.convert13b = function convert13b (ws, len, rws, N) { + var carry = 0; + for (var i = 0; i < len; i++) { + carry = carry + (ws[i] | 0); + + rws[2 * i] = carry & 0x1fff; carry = carry >>> 13; + rws[2 * i + 1] = carry & 0x1fff; carry = carry >>> 13; + } + + // Pad with zeroes + for (i = 2 * len; i < N; ++i) { + rws[i] = 0; + } + + assert(carry === 0); + assert((carry & ~0x1fff) === 0); + }; + + FFTM.prototype.stub = function stub (N) { + var ph = new Array(N); + for (var i = 0; i < N; i++) { + ph[i] = 0; + } + + return ph; + }; + + FFTM.prototype.mulp = function mulp (x, y, out) { + var N = 2 * this.guessLen13b(x.length, y.length); + + var rbt = this.makeRBT(N); + + var _ = this.stub(N); + + var rws = new Array(N); + var rwst = new Array(N); + var iwst = new Array(N); + + var nrws = new Array(N); + var nrwst = new Array(N); + var niwst = new Array(N); + + var rmws = out.words; + rmws.length = N; + + this.convert13b(x.words, x.length, rws, N); + this.convert13b(y.words, y.length, nrws, N); + + this.transform(rws, _, rwst, iwst, N, rbt); + this.transform(nrws, _, nrwst, niwst, N, rbt); + + for (var i = 0; i < N; i++) { + var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i]; + iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i]; + rwst[i] = rx; + } + + this.conjugate(rwst, iwst, N); + this.transform(rwst, iwst, rmws, _, N, rbt); + this.conjugate(rmws, _, N); + this.normalize13b(rmws, N); + + out.negative = x.negative ^ y.negative; + out.length = x.length + y.length; + return out.strip(); + }; + + // Multiply `this` by `num` + BN.prototype.mul = function mul (num) { + var out = new BN(null); + out.words = new Array(this.length + num.length); + return this.mulTo(num, out); + }; + + // Multiply employing FFT + BN.prototype.mulf = function mulf (num) { + var out = new BN(null); + out.words = new Array(this.length + num.length); + return jumboMulTo(this, num, out); + }; + + // In-place Multiplication + BN.prototype.imul = function imul (num) { + return this.clone().mulTo(num, this); + }; + + BN.prototype.imuln = function imuln (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + + // Carry + var carry = 0; + for (var i = 0; i < this.length; i++) { + var w = (this.words[i] | 0) * num; + var lo = (w & 0x3ffffff) + (carry & 0x3ffffff); + carry >>= 26; + carry += (w / 0x4000000) | 0; + // NOTE: lo is 27bit maximum + carry += lo >>> 26; + this.words[i] = lo & 0x3ffffff; + } + + if (carry !== 0) { + this.words[i] = carry; + this.length++; + } + + return this; + }; + + BN.prototype.muln = function muln (num) { + return this.clone().imuln(num); + }; + + // `this` * `this` + BN.prototype.sqr = function sqr () { + return this.mul(this); + }; + + // `this` * `this` in-place + BN.prototype.isqr = function isqr () { + return this.imul(this.clone()); + }; + + // Math.pow(`this`, `num`) + BN.prototype.pow = function pow (num) { + var w = toBitArray(num); + if (w.length === 0) return new BN(1); + + // Skip leading zeroes + var res = this; + for (var i = 0; i < w.length; i++, res = res.sqr()) { + if (w[i] !== 0) break; + } + + if (++i < w.length) { + for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) { + if (w[i] === 0) continue; + + res = res.mul(q); + } + } + + return res; + }; + + // Shift-left in-place + BN.prototype.iushln = function iushln (bits) { + assert(typeof bits === 'number' && bits >= 0); + var r = bits % 26; + var s = (bits - r) / 26; + var carryMask = (0x3ffffff >>> (26 - r)) << (26 - r); + var i; + + if (r !== 0) { + var carry = 0; + + for (i = 0; i < this.length; i++) { + var newCarry = this.words[i] & carryMask; + var c = ((this.words[i] | 0) - newCarry) << r; + this.words[i] = c | carry; + carry = newCarry >>> (26 - r); + } + + if (carry) { + this.words[i] = carry; + this.length++; + } + } + + if (s !== 0) { + for (i = this.length - 1; i >= 0; i--) { + this.words[i + s] = this.words[i]; + } + + for (i = 0; i < s; i++) { + this.words[i] = 0; + } + + this.length += s; + } + + return this.strip(); + }; + + BN.prototype.ishln = function ishln (bits) { + // TODO(indutny): implement me + assert(this.negative === 0); + return this.iushln(bits); + }; + + // Shift-right in-place + // NOTE: `hint` is a lowest bit before trailing zeroes + // NOTE: if `extended` is present - it will be filled with destroyed bits + BN.prototype.iushrn = function iushrn (bits, hint, extended) { + assert(typeof bits === 'number' && bits >= 0); + var h; + if (hint) { + h = (hint - (hint % 26)) / 26; + } else { + h = 0; + } + + var r = bits % 26; + var s = Math.min((bits - r) / 26, this.length); + var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); + var maskedWords = extended; + + h -= s; + h = Math.max(0, h); + + // Extended mode, copy masked part + if (maskedWords) { + for (var i = 0; i < s; i++) { + maskedWords.words[i] = this.words[i]; + } + maskedWords.length = s; + } + + if (s === 0) { + // No-op, we should not move anything at all + } else if (this.length > s) { + this.length -= s; + for (i = 0; i < this.length; i++) { + this.words[i] = this.words[i + s]; + } + } else { + this.words[0] = 0; + this.length = 1; + } + + var carry = 0; + for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) { + var word = this.words[i] | 0; + this.words[i] = (carry << (26 - r)) | (word >>> r); + carry = word & mask; + } + + // Push carried bits as a mask + if (maskedWords && carry !== 0) { + maskedWords.words[maskedWords.length++] = carry; + } + + if (this.length === 0) { + this.words[0] = 0; + this.length = 1; + } + + return this.strip(); + }; + + BN.prototype.ishrn = function ishrn (bits, hint, extended) { + // TODO(indutny): implement me + assert(this.negative === 0); + return this.iushrn(bits, hint, extended); + }; + + // Shift-left + BN.prototype.shln = function shln (bits) { + return this.clone().ishln(bits); + }; + + BN.prototype.ushln = function ushln (bits) { + return this.clone().iushln(bits); + }; + + // Shift-right + BN.prototype.shrn = function shrn (bits) { + return this.clone().ishrn(bits); + }; + + BN.prototype.ushrn = function ushrn (bits) { + return this.clone().iushrn(bits); + }; + + // Test if n bit is set + BN.prototype.testn = function testn (bit) { + assert(typeof bit === 'number' && bit >= 0); + var r = bit % 26; + var s = (bit - r) / 26; + var q = 1 << r; + + // Fast case: bit is much higher than all existing words + if (this.length <= s) return false; + + // Check bit and return + var w = this.words[s]; + + return !!(w & q); + }; + + // Return only lowers bits of number (in-place) + BN.prototype.imaskn = function imaskn (bits) { + assert(typeof bits === 'number' && bits >= 0); + var r = bits % 26; + var s = (bits - r) / 26; + + assert(this.negative === 0, 'imaskn works only with positive numbers'); + + if (this.length <= s) { + return this; + } + + if (r !== 0) { + s++; + } + this.length = Math.min(s, this.length); + + if (r !== 0) { + var mask = 0x3ffffff ^ ((0x3ffffff >>> r) << r); + this.words[this.length - 1] &= mask; + } + + return this.strip(); + }; + + // Return only lowers bits of number + BN.prototype.maskn = function maskn (bits) { + return this.clone().imaskn(bits); + }; + + // Add plain number `num` to `this` + BN.prototype.iaddn = function iaddn (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + if (num < 0) return this.isubn(-num); + + // Possible sign change + if (this.negative !== 0) { + if (this.length === 1 && (this.words[0] | 0) < num) { + this.words[0] = num - (this.words[0] | 0); + this.negative = 0; + return this; + } + + this.negative = 0; + this.isubn(num); + this.negative = 1; + return this; + } + + // Add without checks + return this._iaddn(num); + }; + + BN.prototype._iaddn = function _iaddn (num) { + this.words[0] += num; + + // Carry + for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) { + this.words[i] -= 0x4000000; + if (i === this.length - 1) { + this.words[i + 1] = 1; + } else { + this.words[i + 1]++; + } + } + this.length = Math.max(this.length, i + 1); + + return this; + }; + + // Subtract plain number `num` from `this` + BN.prototype.isubn = function isubn (num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + if (num < 0) return this.iaddn(-num); + + if (this.negative !== 0) { + this.negative = 0; + this.iaddn(num); + this.negative = 1; + return this; + } + + this.words[0] -= num; + + if (this.length === 1 && this.words[0] < 0) { + this.words[0] = -this.words[0]; + this.negative = 1; + } else { + // Carry + for (var i = 0; i < this.length && this.words[i] < 0; i++) { + this.words[i] += 0x4000000; + this.words[i + 1] -= 1; + } + } + + return this.strip(); + }; + + BN.prototype.addn = function addn (num) { + return this.clone().iaddn(num); + }; + + BN.prototype.subn = function subn (num) { + return this.clone().isubn(num); + }; + + BN.prototype.iabs = function iabs () { + this.negative = 0; + + return this; + }; + + BN.prototype.abs = function abs () { + return this.clone().iabs(); + }; + + BN.prototype._ishlnsubmul = function _ishlnsubmul (num, mul, shift) { + var len = num.length + shift; + var i; + + this._expand(len); + + var w; + var carry = 0; + for (i = 0; i < num.length; i++) { + w = (this.words[i + shift] | 0) + carry; + var right = (num.words[i] | 0) * mul; + w -= right & 0x3ffffff; + carry = (w >> 26) - ((right / 0x4000000) | 0); + this.words[i + shift] = w & 0x3ffffff; + } + for (; i < this.length - shift; i++) { + w = (this.words[i + shift] | 0) + carry; + carry = w >> 26; + this.words[i + shift] = w & 0x3ffffff; + } + + if (carry === 0) return this.strip(); + + // Subtraction overflow + assert(carry === -1); + carry = 0; + for (i = 0; i < this.length; i++) { + w = -(this.words[i] | 0) + carry; + carry = w >> 26; + this.words[i] = w & 0x3ffffff; + } + this.negative = 1; + + return this.strip(); + }; + + BN.prototype._wordDiv = function _wordDiv (num, mode) { + var shift = this.length - num.length; + + var a = this.clone(); + var b = num; + + // Normalize + var bhi = b.words[b.length - 1] | 0; + var bhiBits = this._countBits(bhi); + shift = 26 - bhiBits; + if (shift !== 0) { + b = b.ushln(shift); + a.iushln(shift); + bhi = b.words[b.length - 1] | 0; + } + + // Initialize quotient + var m = a.length - b.length; + var q; + + if (mode !== 'mod') { + q = new BN(null); + q.length = m + 1; + q.words = new Array(q.length); + for (var i = 0; i < q.length; i++) { + q.words[i] = 0; + } + } + + var diff = a.clone()._ishlnsubmul(b, 1, m); + if (diff.negative === 0) { + a = diff; + if (q) { + q.words[m] = 1; + } + } + + for (var j = m - 1; j >= 0; j--) { + var qj = (a.words[b.length + j] | 0) * 0x4000000 + + (a.words[b.length + j - 1] | 0); + + // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max + // (0x7ffffff) + qj = Math.min((qj / bhi) | 0, 0x3ffffff); + + a._ishlnsubmul(b, qj, j); + while (a.negative !== 0) { + qj--; + a.negative = 0; + a._ishlnsubmul(b, 1, j); + if (!a.isZero()) { + a.negative ^= 1; + } + } + if (q) { + q.words[j] = qj; + } + } + if (q) { + q.strip(); + } + a.strip(); + + // Denormalize + if (mode !== 'div' && shift !== 0) { + a.iushrn(shift); + } + + return { + div: q || null, + mod: a + }; + }; + + // NOTE: 1) `mode` can be set to `mod` to request mod only, + // to `div` to request div only, or be absent to + // request both div & mod + // 2) `positive` is true if unsigned mod is requested + BN.prototype.divmod = function divmod (num, mode, positive) { + assert(!num.isZero()); + + if (this.isZero()) { + return { + div: new BN(0), + mod: new BN(0) + }; + } + + var div, mod, res; + if (this.negative !== 0 && num.negative === 0) { + res = this.neg().divmod(num, mode); + + if (mode !== 'mod') { + div = res.div.neg(); + } + + if (mode !== 'div') { + mod = res.mod.neg(); + if (positive && mod.negative !== 0) { + mod.iadd(num); + } + } + + return { + div: div, + mod: mod + }; + } + + if (this.negative === 0 && num.negative !== 0) { + res = this.divmod(num.neg(), mode); + + if (mode !== 'mod') { + div = res.div.neg(); + } + + return { + div: div, + mod: res.mod + }; + } + + if ((this.negative & num.negative) !== 0) { + res = this.neg().divmod(num.neg(), mode); + + if (mode !== 'div') { + mod = res.mod.neg(); + if (positive && mod.negative !== 0) { + mod.isub(num); + } + } + + return { + div: res.div, + mod: mod + }; + } + + // Both numbers are positive at this point + + // Strip both numbers to approximate shift value + if (num.length > this.length || this.cmp(num) < 0) { + return { + div: new BN(0), + mod: this + }; + } + + // Very short reduction + if (num.length === 1) { + if (mode === 'div') { + return { + div: this.divn(num.words[0]), + mod: null + }; + } + + if (mode === 'mod') { + return { + div: null, + mod: new BN(this.modn(num.words[0])) + }; + } + + return { + div: this.divn(num.words[0]), + mod: new BN(this.modn(num.words[0])) + }; + } + + return this._wordDiv(num, mode); + }; + + // Find `this` / `num` + BN.prototype.div = function div (num) { + return this.divmod(num, 'div', false).div; + }; + + // Find `this` % `num` + BN.prototype.mod = function mod (num) { + return this.divmod(num, 'mod', false).mod; + }; + + BN.prototype.umod = function umod (num) { + return this.divmod(num, 'mod', true).mod; + }; + + // Find Round(`this` / `num`) + BN.prototype.divRound = function divRound (num) { + var dm = this.divmod(num); + + // Fast case - exact division + if (dm.mod.isZero()) return dm.div; + + var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod; + + var half = num.ushrn(1); + var r2 = num.andln(1); + var cmp = mod.cmp(half); + + // Round down + if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div; + + // Round up + return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1); + }; + + BN.prototype.modn = function modn (num) { + assert(num <= 0x3ffffff); + var p = (1 << 26) % num; + + var acc = 0; + for (var i = this.length - 1; i >= 0; i--) { + acc = (p * acc + (this.words[i] | 0)) % num; + } + + return acc; + }; + + // In-place division by number + BN.prototype.idivn = function idivn (num) { + assert(num <= 0x3ffffff); + + var carry = 0; + for (var i = this.length - 1; i >= 0; i--) { + var w = (this.words[i] | 0) + carry * 0x4000000; + this.words[i] = (w / num) | 0; + carry = w % num; + } + + return this.strip(); + }; + + BN.prototype.divn = function divn (num) { + return this.clone().idivn(num); + }; + + BN.prototype.egcd = function egcd (p) { + assert(p.negative === 0); + assert(!p.isZero()); + + var x = this; + var y = p.clone(); + + if (x.negative !== 0) { + x = x.umod(p); + } else { + x = x.clone(); + } + + // A * x + B * y = x + var A = new BN(1); + var B = new BN(0); + + // C * x + D * y = y + var C = new BN(0); + var D = new BN(1); + + var g = 0; + + while (x.isEven() && y.isEven()) { + x.iushrn(1); + y.iushrn(1); + ++g; + } + + var yp = y.clone(); + var xp = x.clone(); + + while (!x.isZero()) { + for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1); + if (i > 0) { + x.iushrn(i); + while (i-- > 0) { + if (A.isOdd() || B.isOdd()) { + A.iadd(yp); + B.isub(xp); + } + + A.iushrn(1); + B.iushrn(1); + } + } + + for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); + if (j > 0) { + y.iushrn(j); + while (j-- > 0) { + if (C.isOdd() || D.isOdd()) { + C.iadd(yp); + D.isub(xp); + } + + C.iushrn(1); + D.iushrn(1); + } + } + + if (x.cmp(y) >= 0) { + x.isub(y); + A.isub(C); + B.isub(D); + } else { + y.isub(x); + C.isub(A); + D.isub(B); + } + } + + return { + a: C, + b: D, + gcd: y.iushln(g) + }; + }; + + // This is reduced incarnation of the binary EEA + // above, designated to invert members of the + // _prime_ fields F(p) at a maximal speed + BN.prototype._invmp = function _invmp (p) { + assert(p.negative === 0); + assert(!p.isZero()); + + var a = this; + var b = p.clone(); + + if (a.negative !== 0) { + a = a.umod(p); + } else { + a = a.clone(); + } + + var x1 = new BN(1); + var x2 = new BN(0); + + var delta = b.clone(); + + while (a.cmpn(1) > 0 && b.cmpn(1) > 0) { + for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1); + if (i > 0) { + a.iushrn(i); + while (i-- > 0) { + if (x1.isOdd()) { + x1.iadd(delta); + } + + x1.iushrn(1); + } + } + + for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); + if (j > 0) { + b.iushrn(j); + while (j-- > 0) { + if (x2.isOdd()) { + x2.iadd(delta); + } + + x2.iushrn(1); + } + } + + if (a.cmp(b) >= 0) { + a.isub(b); + x1.isub(x2); + } else { + b.isub(a); + x2.isub(x1); + } + } + + var res; + if (a.cmpn(1) === 0) { + res = x1; + } else { + res = x2; + } + + if (res.cmpn(0) < 0) { + res.iadd(p); + } + + return res; + }; + + BN.prototype.gcd = function gcd (num) { + if (this.isZero()) return num.abs(); + if (num.isZero()) return this.abs(); + + var a = this.clone(); + var b = num.clone(); + a.negative = 0; + b.negative = 0; + + // Remove common factor of two + for (var shift = 0; a.isEven() && b.isEven(); shift++) { + a.iushrn(1); + b.iushrn(1); + } + + do { + while (a.isEven()) { + a.iushrn(1); + } + while (b.isEven()) { + b.iushrn(1); + } + + var r = a.cmp(b); + if (r < 0) { + // Swap `a` and `b` to make `a` always bigger than `b` + var t = a; + a = b; + b = t; + } else if (r === 0 || b.cmpn(1) === 0) { + break; + } + + a.isub(b); + } while (true); + + return b.iushln(shift); + }; + + // Invert number in the field F(num) + BN.prototype.invm = function invm (num) { + return this.egcd(num).a.umod(num); + }; + + BN.prototype.isEven = function isEven () { + return (this.words[0] & 1) === 0; + }; + + BN.prototype.isOdd = function isOdd () { + return (this.words[0] & 1) === 1; + }; + + // And first word and num + BN.prototype.andln = function andln (num) { + return this.words[0] & num; + }; + + // Increment at the bit position in-line + BN.prototype.bincn = function bincn (bit) { + assert(typeof bit === 'number'); + var r = bit % 26; + var s = (bit - r) / 26; + var q = 1 << r; + + // Fast case: bit is much higher than all existing words + if (this.length <= s) { + this._expand(s + 1); + this.words[s] |= q; + return this; + } + + // Add bit and propagate, if needed + var carry = q; + for (var i = s; carry !== 0 && i < this.length; i++) { + var w = this.words[i] | 0; + w += carry; + carry = w >>> 26; + w &= 0x3ffffff; + this.words[i] = w; + } + if (carry !== 0) { + this.words[i] = carry; + this.length++; + } + return this; + }; + + BN.prototype.isZero = function isZero () { + return this.length === 1 && this.words[0] === 0; + }; + + BN.prototype.cmpn = function cmpn (num) { + var negative = num < 0; + + if (this.negative !== 0 && !negative) return -1; + if (this.negative === 0 && negative) return 1; + + this.strip(); + + var res; + if (this.length > 1) { + res = 1; + } else { + if (negative) { + num = -num; + } + + assert(num <= 0x3ffffff, 'Number is too big'); + + var w = this.words[0] | 0; + res = w === num ? 0 : w < num ? -1 : 1; + } + if (this.negative !== 0) return -res | 0; + return res; + }; + + // Compare two numbers and return: + // 1 - if `this` > `num` + // 0 - if `this` == `num` + // -1 - if `this` < `num` + BN.prototype.cmp = function cmp (num) { + if (this.negative !== 0 && num.negative === 0) return -1; + if (this.negative === 0 && num.negative !== 0) return 1; + + var res = this.ucmp(num); + if (this.negative !== 0) return -res | 0; + return res; + }; + + // Unsigned comparison + BN.prototype.ucmp = function ucmp (num) { + // At this point both numbers have the same sign + if (this.length > num.length) return 1; + if (this.length < num.length) return -1; + + var res = 0; + for (var i = this.length - 1; i >= 0; i--) { + var a = this.words[i] | 0; + var b = num.words[i] | 0; + + if (a === b) continue; + if (a < b) { + res = -1; + } else if (a > b) { + res = 1; + } + break; + } + return res; + }; + + BN.prototype.gtn = function gtn (num) { + return this.cmpn(num) === 1; + }; + + BN.prototype.gt = function gt (num) { + return this.cmp(num) === 1; + }; + + BN.prototype.gten = function gten (num) { + return this.cmpn(num) >= 0; + }; + + BN.prototype.gte = function gte (num) { + return this.cmp(num) >= 0; + }; + + BN.prototype.ltn = function ltn (num) { + return this.cmpn(num) === -1; + }; + + BN.prototype.lt = function lt (num) { + return this.cmp(num) === -1; + }; + + BN.prototype.lten = function lten (num) { + return this.cmpn(num) <= 0; + }; + + BN.prototype.lte = function lte (num) { + return this.cmp(num) <= 0; + }; + + BN.prototype.eqn = function eqn (num) { + return this.cmpn(num) === 0; + }; + + BN.prototype.eq = function eq (num) { + return this.cmp(num) === 0; + }; + + // + // A reduce context, could be using montgomery or something better, depending + // on the `m` itself. + // + BN.red = function red (num) { + return new Red(num); + }; + + BN.prototype.toRed = function toRed (ctx) { + assert(!this.red, 'Already a number in reduction context'); + assert(this.negative === 0, 'red works only with positives'); + return ctx.convertTo(this)._forceRed(ctx); + }; + + BN.prototype.fromRed = function fromRed () { + assert(this.red, 'fromRed works only with numbers in reduction context'); + return this.red.convertFrom(this); + }; + + BN.prototype._forceRed = function _forceRed (ctx) { + this.red = ctx; + return this; + }; + + BN.prototype.forceRed = function forceRed (ctx) { + assert(!this.red, 'Already a number in reduction context'); + return this._forceRed(ctx); + }; + + BN.prototype.redAdd = function redAdd (num) { + assert(this.red, 'redAdd works only with red numbers'); + return this.red.add(this, num); + }; + + BN.prototype.redIAdd = function redIAdd (num) { + assert(this.red, 'redIAdd works only with red numbers'); + return this.red.iadd(this, num); + }; + + BN.prototype.redSub = function redSub (num) { + assert(this.red, 'redSub works only with red numbers'); + return this.red.sub(this, num); + }; + + BN.prototype.redISub = function redISub (num) { + assert(this.red, 'redISub works only with red numbers'); + return this.red.isub(this, num); + }; + + BN.prototype.redShl = function redShl (num) { + assert(this.red, 'redShl works only with red numbers'); + return this.red.shl(this, num); + }; + + BN.prototype.redMul = function redMul (num) { + assert(this.red, 'redMul works only with red numbers'); + this.red._verify2(this, num); + return this.red.mul(this, num); + }; + + BN.prototype.redIMul = function redIMul (num) { + assert(this.red, 'redMul works only with red numbers'); + this.red._verify2(this, num); + return this.red.imul(this, num); + }; + + BN.prototype.redSqr = function redSqr () { + assert(this.red, 'redSqr works only with red numbers'); + this.red._verify1(this); + return this.red.sqr(this); + }; + + BN.prototype.redISqr = function redISqr () { + assert(this.red, 'redISqr works only with red numbers'); + this.red._verify1(this); + return this.red.isqr(this); + }; + + // Square root over p + BN.prototype.redSqrt = function redSqrt () { + assert(this.red, 'redSqrt works only with red numbers'); + this.red._verify1(this); + return this.red.sqrt(this); + }; + + BN.prototype.redInvm = function redInvm () { + assert(this.red, 'redInvm works only with red numbers'); + this.red._verify1(this); + return this.red.invm(this); + }; + + // Return negative clone of `this` % `red modulo` + BN.prototype.redNeg = function redNeg () { + assert(this.red, 'redNeg works only with red numbers'); + this.red._verify1(this); + return this.red.neg(this); + }; + + BN.prototype.redPow = function redPow (num) { + assert(this.red && !num.red, 'redPow(normalNum)'); + this.red._verify1(this); + return this.red.pow(this, num); + }; + + // Prime numbers with efficient reduction + var primes = { + k256: null, + p224: null, + p192: null, + p25519: null + }; + + // Pseudo-Mersenne prime + function MPrime (name, p) { + // P = 2 ^ N - K + this.name = name; + this.p = new BN(p, 16); + this.n = this.p.bitLength(); + this.k = new BN(1).iushln(this.n).isub(this.p); + + this.tmp = this._tmp(); + } + + MPrime.prototype._tmp = function _tmp () { + var tmp = new BN(null); + tmp.words = new Array(Math.ceil(this.n / 13)); + return tmp; + }; + + MPrime.prototype.ireduce = function ireduce (num) { + // Assumes that `num` is less than `P^2` + // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P) + var r = num; + var rlen; + + do { + this.split(r, this.tmp); + r = this.imulK(r); + r = r.iadd(this.tmp); + rlen = r.bitLength(); + } while (rlen > this.n); + + var cmp = rlen < this.n ? -1 : r.ucmp(this.p); + if (cmp === 0) { + r.words[0] = 0; + r.length = 1; + } else if (cmp > 0) { + r.isub(this.p); + } else { + if (r.strip !== undefined) { + // r is BN v4 instance + r.strip(); + } else { + // r is BN v5 instance + r._strip(); + } + } + + return r; + }; + + MPrime.prototype.split = function split (input, out) { + input.iushrn(this.n, 0, out); + }; + + MPrime.prototype.imulK = function imulK (num) { + return num.imul(this.k); + }; + + function K256 () { + MPrime.call( + this, + 'k256', + 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f'); + } + inherits(K256, MPrime); + + K256.prototype.split = function split (input, output) { + // 256 = 9 * 26 + 22 + var mask = 0x3fffff; + + var outLen = Math.min(input.length, 9); + for (var i = 0; i < outLen; i++) { + output.words[i] = input.words[i]; + } + output.length = outLen; + + if (input.length <= 9) { + input.words[0] = 0; + input.length = 1; + return; + } + + // Shift by 9 limbs + var prev = input.words[9]; + output.words[output.length++] = prev & mask; + + for (i = 10; i < input.length; i++) { + var next = input.words[i] | 0; + input.words[i - 10] = ((next & mask) << 4) | (prev >>> 22); + prev = next; + } + prev >>>= 22; + input.words[i - 10] = prev; + if (prev === 0 && input.length > 10) { + input.length -= 10; + } else { + input.length -= 9; + } + }; + + K256.prototype.imulK = function imulK (num) { + // K = 0x1000003d1 = [ 0x40, 0x3d1 ] + num.words[num.length] = 0; + num.words[num.length + 1] = 0; + num.length += 2; + + // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390 + var lo = 0; + for (var i = 0; i < num.length; i++) { + var w = num.words[i] | 0; + lo += w * 0x3d1; + num.words[i] = lo & 0x3ffffff; + lo = w * 0x40 + ((lo / 0x4000000) | 0); + } + + // Fast length reduction + if (num.words[num.length - 1] === 0) { + num.length--; + if (num.words[num.length - 1] === 0) { + num.length--; + } + } + return num; + }; + + function P224 () { + MPrime.call( + this, + 'p224', + 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001'); + } + inherits(P224, MPrime); + + function P192 () { + MPrime.call( + this, + 'p192', + 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff'); + } + inherits(P192, MPrime); + + function P25519 () { + // 2 ^ 255 - 19 + MPrime.call( + this, + '25519', + '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed'); + } + inherits(P25519, MPrime); + + P25519.prototype.imulK = function imulK (num) { + // K = 0x13 + var carry = 0; + for (var i = 0; i < num.length; i++) { + var hi = (num.words[i] | 0) * 0x13 + carry; + var lo = hi & 0x3ffffff; + hi >>>= 26; + + num.words[i] = lo; + carry = hi; + } + if (carry !== 0) { + num.words[num.length++] = carry; + } + return num; + }; + + // Exported mostly for testing purposes, use plain name instead + BN._prime = function prime (name) { + // Cached version of prime + if (primes[name]) return primes[name]; + + var prime; + if (name === 'k256') { + prime = new K256(); + } else if (name === 'p224') { + prime = new P224(); + } else if (name === 'p192') { + prime = new P192(); + } else if (name === 'p25519') { + prime = new P25519(); + } else { + throw new Error('Unknown prime ' + name); + } + primes[name] = prime; + + return prime; + }; + + // + // Base reduction engine + // + function Red (m) { + if (typeof m === 'string') { + var prime = BN._prime(m); + this.m = prime.p; + this.prime = prime; + } else { + assert(m.gtn(1), 'modulus must be greater than 1'); + this.m = m; + this.prime = null; + } + } + + Red.prototype._verify1 = function _verify1 (a) { + assert(a.negative === 0, 'red works only with positives'); + assert(a.red, 'red works only with red numbers'); + }; + + Red.prototype._verify2 = function _verify2 (a, b) { + assert((a.negative | b.negative) === 0, 'red works only with positives'); + assert(a.red && a.red === b.red, + 'red works only with red numbers'); + }; + + Red.prototype.imod = function imod (a) { + if (this.prime) return this.prime.ireduce(a)._forceRed(this); + return a.umod(this.m)._forceRed(this); + }; + + Red.prototype.neg = function neg (a) { + if (a.isZero()) { + return a.clone(); + } + + return this.m.sub(a)._forceRed(this); + }; + + Red.prototype.add = function add (a, b) { + this._verify2(a, b); + + var res = a.add(b); + if (res.cmp(this.m) >= 0) { + res.isub(this.m); + } + return res._forceRed(this); + }; + + Red.prototype.iadd = function iadd (a, b) { + this._verify2(a, b); + + var res = a.iadd(b); + if (res.cmp(this.m) >= 0) { + res.isub(this.m); + } + return res; + }; + + Red.prototype.sub = function sub (a, b) { + this._verify2(a, b); + + var res = a.sub(b); + if (res.cmpn(0) < 0) { + res.iadd(this.m); + } + return res._forceRed(this); + }; + + Red.prototype.isub = function isub (a, b) { + this._verify2(a, b); + + var res = a.isub(b); + if (res.cmpn(0) < 0) { + res.iadd(this.m); + } + return res; + }; + + Red.prototype.shl = function shl (a, num) { + this._verify1(a); + return this.imod(a.ushln(num)); + }; + + Red.prototype.imul = function imul (a, b) { + this._verify2(a, b); + return this.imod(a.imul(b)); + }; + + Red.prototype.mul = function mul (a, b) { + this._verify2(a, b); + return this.imod(a.mul(b)); + }; + + Red.prototype.isqr = function isqr (a) { + return this.imul(a, a.clone()); + }; + + Red.prototype.sqr = function sqr (a) { + return this.mul(a, a); + }; + + Red.prototype.sqrt = function sqrt (a) { + if (a.isZero()) return a.clone(); + + var mod3 = this.m.andln(3); + assert(mod3 % 2 === 1); + + // Fast case + if (mod3 === 3) { + var pow = this.m.add(new BN(1)).iushrn(2); + return this.pow(a, pow); + } + + // Tonelli-Shanks algorithm (Totally unoptimized and slow) + // + // Find Q and S, that Q * 2 ^ S = (P - 1) + var q = this.m.subn(1); + var s = 0; + while (!q.isZero() && q.andln(1) === 0) { + s++; + q.iushrn(1); + } + assert(!q.isZero()); + + var one = new BN(1).toRed(this); + var nOne = one.redNeg(); + + // Find quadratic non-residue + // NOTE: Max is such because of generalized Riemann hypothesis. + var lpow = this.m.subn(1).iushrn(1); + var z = this.m.bitLength(); + z = new BN(2 * z * z).toRed(this); + + while (this.pow(z, lpow).cmp(nOne) !== 0) { + z.redIAdd(nOne); + } + + var c = this.pow(z, q); + var r = this.pow(a, q.addn(1).iushrn(1)); + var t = this.pow(a, q); + var m = s; + while (t.cmp(one) !== 0) { + var tmp = t; + for (var i = 0; tmp.cmp(one) !== 0; i++) { + tmp = tmp.redSqr(); + } + assert(i < m); + var b = this.pow(c, new BN(1).iushln(m - i - 1)); + + r = r.redMul(b); + c = b.redSqr(); + t = t.redMul(c); + m = i; + } + + return r; + }; + + Red.prototype.invm = function invm (a) { + var inv = a._invmp(this.m); + if (inv.negative !== 0) { + inv.negative = 0; + return this.imod(inv).redNeg(); + } else { + return this.imod(inv); + } + }; + + Red.prototype.pow = function pow (a, num) { + if (num.isZero()) return new BN(1).toRed(this); + if (num.cmpn(1) === 0) return a.clone(); + + var windowSize = 4; + var wnd = new Array(1 << windowSize); + wnd[0] = new BN(1).toRed(this); + wnd[1] = a; + for (var i = 2; i < wnd.length; i++) { + wnd[i] = this.mul(wnd[i - 1], a); + } + + var res = wnd[0]; + var current = 0; + var currentLen = 0; + var start = num.bitLength() % 26; + if (start === 0) { + start = 26; + } + + for (i = num.length - 1; i >= 0; i--) { + var word = num.words[i]; + for (var j = start - 1; j >= 0; j--) { + var bit = (word >> j) & 1; + if (res !== wnd[0]) { + res = this.sqr(res); + } + + if (bit === 0 && current === 0) { + currentLen = 0; + continue; + } + + current <<= 1; + current |= bit; + currentLen++; + if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue; + + res = this.mul(res, wnd[current]); + currentLen = 0; + current = 0; + } + start = 26; + } + + return res; + }; + + Red.prototype.convertTo = function convertTo (num) { + var r = num.umod(this.m); + + return r === num ? r.clone() : r; + }; + + Red.prototype.convertFrom = function convertFrom (num) { + var res = num.clone(); + res.red = null; + return res; + }; + + // + // Montgomery method engine + // + + BN.mont = function mont (num) { + return new Mont(num); + }; + + function Mont (m) { + Red.call(this, m); + + this.shift = this.m.bitLength(); + if (this.shift % 26 !== 0) { + this.shift += 26 - (this.shift % 26); + } + + this.r = new BN(1).iushln(this.shift); + this.r2 = this.imod(this.r.sqr()); + this.rinv = this.r._invmp(this.m); + + this.minv = this.rinv.mul(this.r).isubn(1).div(this.m); + this.minv = this.minv.umod(this.r); + this.minv = this.r.sub(this.minv); + } + inherits(Mont, Red); + + Mont.prototype.convertTo = function convertTo (num) { + return this.imod(num.ushln(this.shift)); + }; + + Mont.prototype.convertFrom = function convertFrom (num) { + var r = this.imod(num.mul(this.rinv)); + r.red = null; + return r; + }; + + Mont.prototype.imul = function imul (a, b) { + if (a.isZero() || b.isZero()) { + a.words[0] = 0; + a.length = 1; + return a; + } + + var t = a.imul(b); + var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); + var u = t.isub(c).iushrn(this.shift); + var res = u; + + if (u.cmp(this.m) >= 0) { + res = u.isub(this.m); + } else if (u.cmpn(0) < 0) { + res = u.iadd(this.m); + } + + return res._forceRed(this); + }; + + Mont.prototype.mul = function mul (a, b) { + if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this); + + var t = a.mul(b); + var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); + var u = t.isub(c).iushrn(this.shift); + var res = u; + if (u.cmp(this.m) >= 0) { + res = u.isub(this.m); + } else if (u.cmpn(0) < 0) { + res = u.iadd(this.m); + } + + return res._forceRed(this); + }; + + Mont.prototype.invm = function invm (a) { + // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R + var res = this.imod(a._invmp(this.m).mul(this.r2)); + return res._forceRed(this); + }; +})(typeof module === 'undefined' || module, this); diff --git a/node_modules/bn.js/package.json b/node_modules/bn.js/package.json new file mode 100644 index 0000000..fe9e479 --- /dev/null +++ b/node_modules/bn.js/package.json @@ -0,0 +1,64 @@ +{ + "_from": "bn.js@^4.0.0", + "_id": "bn.js@4.11.9", + "_inBundle": false, + "_integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "_location": "/bn.js", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "bn.js@^4.0.0", + "name": "bn.js", + "escapedName": "bn.js", + "rawSpec": "^4.0.0", + "saveSpec": null, + "fetchSpec": "^4.0.0" + }, + "_requiredBy": [ + "/asn1.js" + ], + "_resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "_shasum": "26d556829458f9d1e81fc48952493d0ba3507828", + "_spec": "bn.js@^4.0.0", + "_where": "D:\\Users\\user\\Documents\\Portofolio\\Github\\WebsiteFootballPWA\\node_modules\\asn1.js", + "author": { + "name": "Fedor Indutny", + "email": "fedor@indutny.com" + }, + "browser": { + "buffer": false + }, + "bugs": { + "url": "https://github.com/indutny/bn.js/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Big number implementation in pure javascript", + "devDependencies": { + "istanbul": "^0.3.5", + "mocha": "^2.1.0", + "semistandard": "^7.0.4" + }, + "homepage": "https://github.com/indutny/bn.js", + "keywords": [ + "BN", + "BigNum", + "Big number", + "Modulo", + "Montgomery" + ], + "license": "MIT", + "main": "lib/bn.js", + "name": "bn.js", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/indutny/bn.js.git" + }, + "scripts": { + "lint": "semistandard", + "test": "npm run lint && npm run unit", + "unit": "mocha --reporter=spec test/*-test.js" + }, + "version": "4.11.9" +} diff --git a/node_modules/bn.js/util/genCombMulTo.js b/node_modules/bn.js/util/genCombMulTo.js new file mode 100644 index 0000000..8b456c7 --- /dev/null +++ b/node_modules/bn.js/util/genCombMulTo.js @@ -0,0 +1,65 @@ +'use strict'; + +// NOTE: This could be potentionally used to generate loop-less multiplications +function genCombMulTo (alen, blen) { + var len = alen + blen - 1; + var src = [ + 'var a = self.words;', + 'var b = num.words;', + 'var o = out.words;', + 'var c = 0;', + 'var lo;', + 'var mid;', + 'var hi;' + ]; + for (var i = 0; i < alen; i++) { + src.push('var a' + i + ' = a[' + i + '] | 0;'); + src.push('var al' + i + ' = a' + i + ' & 0x1fff;'); + src.push('var ah' + i + ' = a' + i + ' >>> 13;'); + } + for (i = 0; i < blen; i++) { + src.push('var b' + i + ' = b[' + i + '] | 0;'); + src.push('var bl' + i + ' = b' + i + ' & 0x1fff;'); + src.push('var bh' + i + ' = b' + i + ' >>> 13;'); + } + src.push(''); + src.push('out.negative = self.negative ^ num.negative;'); + src.push('out.length = ' + len + ';'); + + for (var k = 0; k < len; k++) { + var minJ = Math.max(0, k - alen + 1); + var maxJ = Math.min(k, blen - 1); + + src.push('\/* k = ' + k + ' *\/'); + src.push('var w' + k + ' = c;'); + src.push('c = 0;'); + for (var j = minJ; j <= maxJ; j++) { + i = k - j; + + src.push('lo = Math.imul(al' + i + ', bl' + j + ');'); + src.push('mid = Math.imul(al' + i + ', bh' + j + ');'); + src.push('mid = (mid + Math.imul(ah' + i + ', bl' + j + ')) | 0;'); + src.push('hi = Math.imul(ah' + i + ', bh' + j + ');'); + + src.push('w' + k + ' = (w' + k + ' + lo) | 0;'); + src.push('w' + k + ' = (w' + k + ' + ((mid & 0x1fff) << 13)) | 0;'); + src.push('c = (c + hi) | 0;'); + src.push('c = (c + (mid >>> 13)) | 0;'); + src.push('c = (c + (w' + k + ' >>> 26)) | 0;'); + src.push('w' + k + ' &= 0x3ffffff;'); + } + } + // Store in separate step for better memory access + for (k = 0; k < len; k++) { + src.push('o[' + k + '] = w' + k + ';'); + } + src.push('if (c !== 0) {', + ' o[' + k + '] = c;', + ' out.length++;', + '}', + 'return out;'); + + return src.join('\n'); +} + +console.log(genCombMulTo(10, 10)); diff --git a/node_modules/bn.js/util/genCombMulTo10.js b/node_modules/bn.js/util/genCombMulTo10.js new file mode 100644 index 0000000..cf2e6e8 --- /dev/null +++ b/node_modules/bn.js/util/genCombMulTo10.js @@ -0,0 +1,65 @@ +'use strict'; + +function genCombMulTo (alen, blen) { + var len = alen + blen - 1; + var src = [ + 'var a = self.words;', + 'var b = num.words;', + 'var o = out.words;', + 'var c = 0;', + 'var lo;', + 'var mid;', + 'var hi;' + ]; + for (var i = 0; i < alen; i++) { + src.push('var a' + i + ' = a[' + i + '] | 0;'); + src.push('var al' + i + ' = a' + i + ' & 0x1fff;'); + src.push('var ah' + i + ' = a' + i + ' >>> 13;'); + } + for (i = 0; i < blen; i++) { + src.push('var b' + i + ' = b[' + i + '] | 0;'); + src.push('var bl' + i + ' = b' + i + ' & 0x1fff;'); + src.push('var bh' + i + ' = b' + i + ' >>> 13;'); + } + src.push(''); + src.push('out.negative = self.negative ^ num.negative;'); + src.push('out.length = ' + len + ';'); + + for (var k = 0; k < len; k++) { + var minJ = Math.max(0, k - alen + 1); + var maxJ = Math.min(k, blen - 1); + + src.push('\/* k = ' + k + ' *\/'); + src.push('lo = Math.imul(al' + (k - minJ) + ', bl' + minJ + ');'); + src.push('mid = Math.imul(al' + (k - minJ) + ', bh' + minJ + ');'); + src.push( + 'mid = (mid + Math.imul(ah' + (k - minJ) + ', bl' + minJ + ')) | 0;'); + src.push('hi = Math.imul(ah' + (k - minJ) + ', bh' + minJ + ');'); + + for (var j = minJ + 1; j <= maxJ; j++) { + i = k - j; + + src.push('lo = (lo + Math.imul(al' + i + ', bl' + j + ')) | 0;'); + src.push('mid = (mid + Math.imul(al' + i + ', bh' + j + ')) | 0;'); + src.push('mid = (mid + Math.imul(ah' + i + ', bl' + j + ')) | 0;'); + src.push('hi = (hi + Math.imul(ah' + i + ', bh' + j + ')) | 0;'); + } + + src.push('var w' + k + ' = (((c + lo) | 0) + ((mid & 0x1fff) << 13)) | 0;'); + src.push('c = (((hi + (mid >>> 13)) | 0) + (w' + k + ' >>> 26)) | 0;'); + src.push('w' + k + ' &= 0x3ffffff;'); + } + // Store in separate step for better memory access + for (k = 0; k < len; k++) { + src.push('o[' + k + '] = w' + k + ';'); + } + src.push('if (c !== 0) {', + ' o[' + k + '] = c;', + ' out.length++;', + '}', + 'return out;'); + + return src.join('\n'); +} + +console.log(genCombMulTo(10, 10)); diff --git a/node_modules/buffer-equal-constant-time/.npmignore b/node_modules/buffer-equal-constant-time/.npmignore new file mode 100644 index 0000000..34e4f5c --- /dev/null +++ b/node_modules/buffer-equal-constant-time/.npmignore @@ -0,0 +1,2 @@ +.*.sw[mnop] +node_modules/ diff --git a/node_modules/buffer-equal-constant-time/.travis.yml b/node_modules/buffer-equal-constant-time/.travis.yml new file mode 100644 index 0000000..78e1c01 --- /dev/null +++ b/node_modules/buffer-equal-constant-time/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: +- "0.11" +- "0.10" diff --git a/node_modules/buffer-equal-constant-time/LICENSE.txt b/node_modules/buffer-equal-constant-time/LICENSE.txt new file mode 100644 index 0000000..9a064f3 --- /dev/null +++ b/node_modules/buffer-equal-constant-time/LICENSE.txt @@ -0,0 +1,12 @@ +Copyright (c) 2013, GoInstant Inc., a salesforce.com company +All rights reserved. + +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 salesforce.com, nor GoInstant, 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/node_modules/buffer-equal-constant-time/README.md b/node_modules/buffer-equal-constant-time/README.md new file mode 100644 index 0000000..4f227f5 --- /dev/null +++ b/node_modules/buffer-equal-constant-time/README.md @@ -0,0 +1,50 @@ +# buffer-equal-constant-time + +Constant-time `Buffer` comparison for node.js. Should work with browserify too. + +[![Build Status](https://travis-ci.org/goinstant/buffer-equal-constant-time.png?branch=master)](https://travis-ci.org/goinstant/buffer-equal-constant-time) + +```sh + npm install buffer-equal-constant-time +``` + +# Usage + +```js + var bufferEq = require('buffer-equal-constant-time'); + + var a = new Buffer('asdf'); + var b = new Buffer('asdf'); + if (bufferEq(a,b)) { + // the same! + } else { + // different in at least one byte! + } +``` + +If you'd like to install an `.equal()` method onto the node.js `Buffer` and +`SlowBuffer` prototypes: + +```js + require('buffer-equal-constant-time').install(); + + var a = new Buffer('asdf'); + var b = new Buffer('asdf'); + if (a.equal(b)) { + // the same! + } else { + // different in at least one byte! + } +``` + +To get rid of the installed `.equal()` method, call `.restore()`: + +```js + require('buffer-equal-constant-time').restore(); +``` + +# Legal + +© 2013 GoInstant Inc., a salesforce.com company + +Licensed under the BSD 3-clause license. diff --git a/node_modules/buffer-equal-constant-time/index.js b/node_modules/buffer-equal-constant-time/index.js new file mode 100644 index 0000000..5462c1f --- /dev/null +++ b/node_modules/buffer-equal-constant-time/index.js @@ -0,0 +1,41 @@ +/*jshint node:true */ +'use strict'; +var Buffer = require('buffer').Buffer; // browserify +var SlowBuffer = require('buffer').SlowBuffer; + +module.exports = bufferEq; + +function bufferEq(a, b) { + + // shortcutting on type is necessary for correctness + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + return false; + } + + // buffer sizes should be well-known information, so despite this + // shortcutting, it doesn't leak any information about the *contents* of the + // buffers. + if (a.length !== b.length) { + return false; + } + + var c = 0; + for (var i = 0; i < a.length; i++) { + /*jshint bitwise:false */ + c |= a[i] ^ b[i]; // XOR + } + return c === 0; +} + +bufferEq.install = function() { + Buffer.prototype.equal = SlowBuffer.prototype.equal = function equal(that) { + return bufferEq(this, that); + }; +}; + +var origBufEqual = Buffer.prototype.equal; +var origSlowBufEqual = SlowBuffer.prototype.equal; +bufferEq.restore = function() { + Buffer.prototype.equal = origBufEqual; + SlowBuffer.prototype.equal = origSlowBufEqual; +}; diff --git a/node_modules/buffer-equal-constant-time/package.json b/node_modules/buffer-equal-constant-time/package.json new file mode 100644 index 0000000..6600bae --- /dev/null +++ b/node_modules/buffer-equal-constant-time/package.json @@ -0,0 +1,55 @@ +{ + "_from": "buffer-equal-constant-time@1.0.1", + "_id": "buffer-equal-constant-time@1.0.1", + "_inBundle": false, + "_integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=", + "_location": "/buffer-equal-constant-time", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "buffer-equal-constant-time@1.0.1", + "name": "buffer-equal-constant-time", + "escapedName": "buffer-equal-constant-time", + "rawSpec": "1.0.1", + "saveSpec": null, + "fetchSpec": "1.0.1" + }, + "_requiredBy": [ + "/jwa" + ], + "_resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "_shasum": "f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819", + "_spec": "buffer-equal-constant-time@1.0.1", + "_where": "D:\\Users\\user\\Documents\\Portofolio\\Github\\WebsiteFootballPWA\\node_modules\\jwa", + "author": { + "name": "GoInstant Inc., a salesforce.com company" + }, + "bugs": { + "url": "https://github.com/goinstant/buffer-equal-constant-time/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Constant-time comparison of Buffers", + "devDependencies": { + "mocha": "~1.15.1" + }, + "homepage": "https://github.com/goinstant/buffer-equal-constant-time#readme", + "keywords": [ + "buffer", + "equal", + "constant-time", + "crypto" + ], + "license": "BSD-3-Clause", + "main": "index.js", + "name": "buffer-equal-constant-time", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/goinstant/buffer-equal-constant-time.git" + }, + "scripts": { + "test": "mocha test.js" + }, + "version": "1.0.1" +} diff --git a/node_modules/buffer-equal-constant-time/test.js b/node_modules/buffer-equal-constant-time/test.js new file mode 100644 index 0000000..0bc972d --- /dev/null +++ b/node_modules/buffer-equal-constant-time/test.js @@ -0,0 +1,42 @@ +/*jshint node:true */ +'use strict'; + +var bufferEq = require('./index'); +var assert = require('assert'); + +describe('buffer-equal-constant-time', function() { + var a = new Buffer('asdfasdf123456'); + var b = new Buffer('asdfasdf123456'); + var c = new Buffer('asdfasdf'); + + describe('bufferEq', function() { + it('says a == b', function() { + assert.strictEqual(bufferEq(a, b), true); + }); + + it('says a != c', function() { + assert.strictEqual(bufferEq(a, c), false); + }); + }); + + describe('install/restore', function() { + before(function() { + bufferEq.install(); + }); + after(function() { + bufferEq.restore(); + }); + + it('installed an .equal method', function() { + var SlowBuffer = require('buffer').SlowBuffer; + assert.ok(Buffer.prototype.equal); + assert.ok(SlowBuffer.prototype.equal); + }); + + it('infected existing Buffers', function() { + assert.strictEqual(a.equal(b), true); + assert.strictEqual(a.equal(c), false); + }); + }); + +}); diff --git a/node_modules/debug/LICENSE b/node_modules/debug/LICENSE new file mode 100644 index 0000000..658c933 --- /dev/null +++ b/node_modules/debug/LICENSE @@ -0,0 +1,19 @@ +(The MIT License) + +Copyright (c) 2014 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/node_modules/debug/README.md b/node_modules/debug/README.md new file mode 100644 index 0000000..88dae35 --- /dev/null +++ b/node_modules/debug/README.md @@ -0,0 +1,455 @@ +# debug +[![Build Status](https://travis-ci.org/visionmedia/debug.svg?branch=master)](https://travis-ci.org/visionmedia/debug) [![Coverage Status](https://coveralls.io/repos/github/visionmedia/debug/badge.svg?branch=master)](https://coveralls.io/github/visionmedia/debug?branch=master) [![Slack](https://visionmedia-community-slackin.now.sh/badge.svg)](https://visionmedia-community-slackin.now.sh/) [![OpenCollective](https://opencollective.com/debug/backers/badge.svg)](#backers) +[![OpenCollective](https://opencollective.com/debug/sponsors/badge.svg)](#sponsors) + + + +A tiny JavaScript debugging utility modelled after Node.js core's debugging +technique. Works in Node.js and web browsers. + +## Installation + +```bash +$ npm install debug +``` + +## Usage + +`debug` exposes a function; simply pass this function the name of your module, and it will return a decorated version of `console.error` for you to pass debug statements to. This will allow you to toggle the debug output for different parts of your module as well as the module as a whole. + +Example [_app.js_](./examples/node/app.js): + +```js +var debug = require('debug')('http') + , http = require('http') + , name = 'My App'; + +// fake app + +debug('booting %o', name); + +http.createServer(function(req, res){ + debug(req.method + ' ' + req.url); + res.end('hello\n'); +}).listen(3000, function(){ + debug('listening'); +}); + +// fake worker of some kind + +require('./worker'); +``` + +Example [_worker.js_](./examples/node/worker.js): + +```js +var a = require('debug')('worker:a') + , b = require('debug')('worker:b'); + +function work() { + a('doing lots of uninteresting work'); + setTimeout(work, Math.random() * 1000); +} + +work(); + +function workb() { + b('doing some work'); + setTimeout(workb, Math.random() * 2000); +} + +workb(); +``` + +The `DEBUG` environment variable is then used to enable these based on space or +comma-delimited names. + +Here are some examples: + +screen shot 2017-08-08 at 12 53 04 pm +screen shot 2017-08-08 at 12 53 38 pm +screen shot 2017-08-08 at 12 53 25 pm + +#### Windows command prompt notes + +##### CMD + +On Windows the environment variable is set using the `set` command. + +```cmd +set DEBUG=*,-not_this +``` + +Example: + +```cmd +set DEBUG=* & node app.js +``` + +##### PowerShell (VS Code default) + +PowerShell uses different syntax to set environment variables. + +```cmd +$env:DEBUG = "*,-not_this" +``` + +Example: + +```cmd +$env:DEBUG='app';node app.js +``` + +Then, run the program to be debugged as usual. + +npm script example: +```js + "windowsDebug": "@powershell -Command $env:DEBUG='*';node app.js", +``` + +## Namespace Colors + +Every debug instance has a color generated for it based on its namespace name. +This helps when visually parsing the debug output to identify which debug instance +a debug line belongs to. + +#### Node.js + +In Node.js, colors are enabled when stderr is a TTY. You also _should_ install +the [`supports-color`](https://npmjs.org/supports-color) module alongside debug, +otherwise debug will only use a small handful of basic colors. + + + +#### Web Browser + +Colors are also enabled on "Web Inspectors" that understand the `%c` formatting +option. These are WebKit web inspectors, Firefox ([since version +31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/)) +and the Firebug plugin for Firefox (any version). + + + + +## Millisecond diff + +When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls. + + + +When stdout is not a TTY, `Date#toISOString()` is used, making it more useful for logging the debug information as shown below: + + + + +## Conventions + +If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser". If you append a "*" to the end of your name, it will always be enabled regardless of the setting of the DEBUG environment variable. You can then use it for normal output as well as debug output. + +## Wildcards + +The `*` character may be used as a wildcard. Suppose for example your library has +debuggers named "connect:bodyParser", "connect:compress", "connect:session", +instead of listing all three with +`DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do +`DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`. + +You can also exclude specific debuggers by prefixing them with a "-" character. +For example, `DEBUG=*,-connect:*` would include all debuggers except those +starting with "connect:". + +## Environment Variables + +When running through Node.js, you can set a few environment variables that will +change the behavior of the debug logging: + +| Name | Purpose | +|-----------|-------------------------------------------------| +| `DEBUG` | Enables/disables specific debugging namespaces. | +| `DEBUG_HIDE_DATE` | Hide date from debug output (non-TTY). | +| `DEBUG_COLORS`| Whether or not to use colors in the debug output. | +| `DEBUG_DEPTH` | Object inspection depth. | +| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. | + + +__Note:__ The environment variables beginning with `DEBUG_` end up being +converted into an Options object that gets used with `%o`/`%O` formatters. +See the Node.js documentation for +[`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options) +for the complete list. + +## Formatters + +Debug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting. +Below are the officially supported formatters: + +| Formatter | Representation | +|-----------|----------------| +| `%O` | Pretty-print an Object on multiple lines. | +| `%o` | Pretty-print an Object all on a single line. | +| `%s` | String. | +| `%d` | Number (both integer and float). | +| `%j` | JSON. Replaced with the string '[Circular]' if the argument contains circular references. | +| `%%` | Single percent sign ('%'). This does not consume an argument. | + + +### Custom formatters + +You can add custom formatters by extending the `debug.formatters` object. +For example, if you wanted to add support for rendering a Buffer as hex with +`%h`, you could do something like: + +```js +const createDebug = require('debug') +createDebug.formatters.h = (v) => { + return v.toString('hex') +} + +// …elsewhere +const debug = createDebug('foo') +debug('this is hex: %h', new Buffer('hello world')) +// foo this is hex: 68656c6c6f20776f726c6421 +0ms +``` + + +## Browser Support + +You can build a browser-ready script using [browserify](https://github.com/substack/node-browserify), +or just use the [browserify-as-a-service](https://wzrd.in/) [build](https://wzrd.in/standalone/debug@latest), +if you don't want to build it yourself. + +Debug's enable state is currently persisted by `localStorage`. +Consider the situation shown below where you have `worker:a` and `worker:b`, +and wish to debug both. You can enable this using `localStorage.debug`: + +```js +localStorage.debug = 'worker:*' +``` + +And then refresh the page. + +```js +a = debug('worker:a'); +b = debug('worker:b'); + +setInterval(function(){ + a('doing some work'); +}, 1000); + +setInterval(function(){ + b('doing some work'); +}, 1200); +``` + + +## Output streams + + By default `debug` will log to stderr, however this can be configured per-namespace by overriding the `log` method: + +Example [_stdout.js_](./examples/node/stdout.js): + +```js +var debug = require('debug'); +var error = debug('app:error'); + +// by default stderr is used +error('goes to stderr!'); + +var log = debug('app:log'); +// set this namespace to log via console.log +log.log = console.log.bind(console); // don't forget to bind to console! +log('goes to stdout'); +error('still goes to stderr!'); + +// set all output to go via console.info +// overrides all per-namespace log settings +debug.log = console.info.bind(console); +error('now goes to stdout via console.info'); +log('still goes to stdout, but via console.info now'); +``` + +## Extend +You can simply extend debugger +```js +const log = require('debug')('auth'); + +//creates new debug instance with extended namespace +const logSign = log.extend('sign'); +const logLogin = log.extend('login'); + +log('hello'); // auth hello +logSign('hello'); //auth:sign hello +logLogin('hello'); //auth:login hello +``` + +## Set dynamically + +You can also enable debug dynamically by calling the `enable()` method : + +```js +let debug = require('debug'); + +console.log(1, debug.enabled('test')); + +debug.enable('test'); +console.log(2, debug.enabled('test')); + +debug.disable(); +console.log(3, debug.enabled('test')); + +``` + +print : +``` +1 false +2 true +3 false +``` + +Usage : +`enable(namespaces)` +`namespaces` can include modes separated by a colon and wildcards. + +Note that calling `enable()` completely overrides previously set DEBUG variable : + +``` +$ DEBUG=foo node -e 'var dbg = require("debug"); dbg.enable("bar"); console.log(dbg.enabled("foo"))' +=> false +``` + +`disable()` + +Will disable all namespaces. The functions returns the namespaces currently +enabled (and skipped). This can be useful if you want to disable debugging +temporarily without knowing what was enabled to begin with. + +For example: + +```js +let debug = require('debug'); +debug.enable('foo:*,-foo:bar'); +let namespaces = debug.disable(); +debug.enable(namespaces); +``` + +Note: There is no guarantee that the string will be identical to the initial +enable string, but semantically they will be identical. + +## Checking whether a debug target is enabled + +After you've created a debug instance, you can determine whether or not it is +enabled by checking the `enabled` property: + +```javascript +const debug = require('debug')('http'); + +if (debug.enabled) { + // do stuff... +} +``` + +You can also manually toggle this property to force the debug instance to be +enabled or disabled. + + +## Authors + + - TJ Holowaychuk + - Nathan Rajlich + - Andrew Rhyne + +## Backers + +Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/debug#backer)] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## Sponsors + +Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/debug#sponsor)] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +## License + +(The MIT License) + +Copyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/debug/package.json b/node_modules/debug/package.json new file mode 100644 index 0000000..4a10dd2 --- /dev/null +++ b/node_modules/debug/package.json @@ -0,0 +1,102 @@ +{ + "_from": "debug@4", + "_id": "debug@4.3.1", + "_inBundle": false, + "_integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "_location": "/debug", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "debug@4", + "name": "debug", + "escapedName": "debug", + "rawSpec": "4", + "saveSpec": null, + "fetchSpec": "4" + }, + "_requiredBy": [ + "/agent-base", + "/https-proxy-agent" + ], + "_resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "_shasum": "f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee", + "_spec": "debug@4", + "_where": "D:\\Users\\user\\Documents\\Portofolio\\Github\\WebsiteFootballPWA\\node_modules\\https-proxy-agent", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "browser": "./src/browser.js", + "bugs": { + "url": "https://github.com/visionmedia/debug/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "name": "Nathan Rajlich", + "email": "nathan@tootallnate.net", + "url": "http://n8.io" + }, + { + "name": "Andrew Rhyne", + "email": "rhyneandrew@gmail.com" + }, + { + "name": "Josh Junon", + "email": "josh@junon.me" + } + ], + "dependencies": { + "ms": "2.1.2" + }, + "deprecated": false, + "description": "small debugging utility", + "devDependencies": { + "brfs": "^2.0.1", + "browserify": "^16.2.3", + "coveralls": "^3.0.2", + "istanbul": "^0.4.5", + "karma": "^3.1.4", + "karma-browserify": "^6.0.0", + "karma-chrome-launcher": "^2.2.0", + "karma-mocha": "^1.3.0", + "mocha": "^5.2.0", + "mocha-lcov-reporter": "^1.2.0", + "xo": "^0.23.0" + }, + "engines": { + "node": ">=6.0" + }, + "files": [ + "src", + "LICENSE", + "README.md" + ], + "homepage": "https://github.com/visionmedia/debug#readme", + "keywords": [ + "debug", + "log", + "debugger" + ], + "license": "MIT", + "main": "./src/index.js", + "name": "debug", + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + }, + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/debug.git" + }, + "scripts": { + "lint": "xo", + "test": "npm run test:node && npm run test:browser && npm run lint", + "test:browser": "karma start --single-run", + "test:coverage": "cat ./coverage/lcov.info | coveralls", + "test:node": "istanbul cover _mocha -- test.js" + }, + "version": "4.3.1" +} diff --git a/node_modules/debug/src/browser.js b/node_modules/debug/src/browser.js new file mode 100644 index 0000000..cd0fc35 --- /dev/null +++ b/node_modules/debug/src/browser.js @@ -0,0 +1,269 @@ +/* eslint-env browser */ + +/** + * This is the web browser implementation of `debug()`. + */ + +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.storage = localstorage(); +exports.destroy = (() => { + let warned = false; + + return () => { + if (!warned) { + warned = true; + console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'); + } + }; +})(); + +/** + * Colors. + */ + +exports.colors = [ + '#0000CC', + '#0000FF', + '#0033CC', + '#0033FF', + '#0066CC', + '#0066FF', + '#0099CC', + '#0099FF', + '#00CC00', + '#00CC33', + '#00CC66', + '#00CC99', + '#00CCCC', + '#00CCFF', + '#3300CC', + '#3300FF', + '#3333CC', + '#3333FF', + '#3366CC', + '#3366FF', + '#3399CC', + '#3399FF', + '#33CC00', + '#33CC33', + '#33CC66', + '#33CC99', + '#33CCCC', + '#33CCFF', + '#6600CC', + '#6600FF', + '#6633CC', + '#6633FF', + '#66CC00', + '#66CC33', + '#9900CC', + '#9900FF', + '#9933CC', + '#9933FF', + '#99CC00', + '#99CC33', + '#CC0000', + '#CC0033', + '#CC0066', + '#CC0099', + '#CC00CC', + '#CC00FF', + '#CC3300', + '#CC3333', + '#CC3366', + '#CC3399', + '#CC33CC', + '#CC33FF', + '#CC6600', + '#CC6633', + '#CC9900', + '#CC9933', + '#CCCC00', + '#CCCC33', + '#FF0000', + '#FF0033', + '#FF0066', + '#FF0099', + '#FF00CC', + '#FF00FF', + '#FF3300', + '#FF3333', + '#FF3366', + '#FF3399', + '#FF33CC', + '#FF33FF', + '#FF6600', + '#FF6633', + '#FF9900', + '#FF9933', + '#FFCC00', + '#FFCC33' +]; + +/** + * Currently only WebKit-based Web Inspectors, Firefox >= v31, + * and the Firebug extension (any Firefox version) are known + * to support "%c" CSS customizations. + * + * TODO: add a `localStorage` variable to explicitly enable/disable colors + */ + +// eslint-disable-next-line complexity +function useColors() { + // NB: In an Electron preload script, document will be defined but not fully + // initialized. Since we know we're in Chrome, we'll just detect this case + // explicitly + if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) { + return true; + } + + // Internet Explorer and Edge do not support colors. + if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) { + return false; + } + + // Is webkit? http://stackoverflow.com/a/16459606/376773 + // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632 + return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) || + // Is firebug? http://stackoverflow.com/a/398120/376773 + (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) || + // Is firefox >= v31? + // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) || + // Double check webkit in userAgent just in case we are in a worker + (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)); +} + +/** + * Colorize log arguments if enabled. + * + * @api public + */ + +function formatArgs(args) { + args[0] = (this.useColors ? '%c' : '') + + this.namespace + + (this.useColors ? ' %c' : ' ') + + args[0] + + (this.useColors ? '%c ' : ' ') + + '+' + module.exports.humanize(this.diff); + + if (!this.useColors) { + return; + } + + const c = 'color: ' + this.color; + args.splice(1, 0, c, 'color: inherit'); + + // The final "%c" is somewhat tricky, because there could be other + // arguments passed either before or after the %c, so we need to + // figure out the correct index to insert the CSS into + let index = 0; + let lastC = 0; + args[0].replace(/%[a-zA-Z%]/g, match => { + if (match === '%%') { + return; + } + index++; + if (match === '%c') { + // We only are interested in the *last* %c + // (the user may have provided their own) + lastC = index; + } + }); + + args.splice(lastC, 0, c); +} + +/** + * Invokes `console.debug()` when available. + * No-op when `console.debug` is not a "function". + * If `console.debug` is not available, falls back + * to `console.log`. + * + * @api public + */ +exports.log = console.debug || console.log || (() => {}); + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ +function save(namespaces) { + try { + if (namespaces) { + exports.storage.setItem('debug', namespaces); + } else { + exports.storage.removeItem('debug'); + } + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ +function load() { + let r; + try { + r = exports.storage.getItem('debug'); + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } + + // If debug isn't set in LS, and we're in Electron, try to load $DEBUG + if (!r && typeof process !== 'undefined' && 'env' in process) { + r = process.env.DEBUG; + } + + return r; +} + +/** + * Localstorage attempts to return the localstorage. + * + * This is necessary because safari throws + * when a user disables cookies/localstorage + * and you attempt to access it. + * + * @return {LocalStorage} + * @api private + */ + +function localstorage() { + try { + // TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context + // The Browser also has localStorage in the global context. + return localStorage; + } catch (error) { + // Swallow + // XXX (@Qix-) should we be logging these? + } +} + +module.exports = require('./common')(exports); + +const {formatters} = module.exports; + +/** + * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default. + */ + +formatters.j = function (v) { + try { + return JSON.stringify(v); + } catch (error) { + return '[UnexpectedJSONParseError]: ' + error.message; + } +}; diff --git a/node_modules/debug/src/common.js b/node_modules/debug/src/common.js new file mode 100644 index 0000000..392a8e0 --- /dev/null +++ b/node_modules/debug/src/common.js @@ -0,0 +1,261 @@ + +/** + * This is the common logic for both the Node.js and web browser + * implementations of `debug()`. + */ + +function setup(env) { + createDebug.debug = createDebug; + createDebug.default = createDebug; + createDebug.coerce = coerce; + createDebug.disable = disable; + createDebug.enable = enable; + createDebug.enabled = enabled; + createDebug.humanize = require('ms'); + createDebug.destroy = destroy; + + Object.keys(env).forEach(key => { + createDebug[key] = env[key]; + }); + + /** + * The currently active debug mode names, and names to skip. + */ + + createDebug.names = []; + createDebug.skips = []; + + /** + * Map of special "%n" handling functions, for the debug "format" argument. + * + * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N". + */ + createDebug.formatters = {}; + + /** + * Selects a color for a debug namespace + * @param {String} namespace The namespace string for the for the debug instance to be colored + * @return {Number|String} An ANSI color code for the given namespace + * @api private + */ + function selectColor(namespace) { + let hash = 0; + + for (let i = 0; i < namespace.length; i++) { + hash = ((hash << 5) - hash) + namespace.charCodeAt(i); + hash |= 0; // Convert to 32bit integer + } + + return createDebug.colors[Math.abs(hash) % createDebug.colors.length]; + } + createDebug.selectColor = selectColor; + + /** + * Create a debugger with the given `namespace`. + * + * @param {String} namespace + * @return {Function} + * @api public + */ + function createDebug(namespace) { + let prevTime; + let enableOverride = null; + + function debug(...args) { + // Disabled? + if (!debug.enabled) { + return; + } + + const self = debug; + + // Set `diff` timestamp + const curr = Number(new Date()); + const ms = curr - (prevTime || curr); + self.diff = ms; + self.prev = prevTime; + self.curr = curr; + prevTime = curr; + + args[0] = createDebug.coerce(args[0]); + + if (typeof args[0] !== 'string') { + // Anything else let's inspect with %O + args.unshift('%O'); + } + + // Apply any `formatters` transformations + let index = 0; + args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => { + // If we encounter an escaped % then don't increase the array index + if (match === '%%') { + return '%'; + } + index++; + const formatter = createDebug.formatters[format]; + if (typeof formatter === 'function') { + const val = args[index]; + match = formatter.call(self, val); + + // Now we need to remove `args[index]` since it's inlined in the `format` + args.splice(index, 1); + index--; + } + return match; + }); + + // Apply env-specific formatting (colors, etc.) + createDebug.formatArgs.call(self, args); + + const logFn = self.log || createDebug.log; + logFn.apply(self, args); + } + + debug.namespace = namespace; + debug.useColors = createDebug.useColors(); + debug.color = createDebug.selectColor(namespace); + debug.extend = extend; + debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release. + + Object.defineProperty(debug, 'enabled', { + enumerable: true, + configurable: false, + get: () => enableOverride === null ? createDebug.enabled(namespace) : enableOverride, + set: v => { + enableOverride = v; + } + }); + + // Env-specific initialization logic for debug instances + if (typeof createDebug.init === 'function') { + createDebug.init(debug); + } + + return debug; + } + + function extend(namespace, delimiter) { + const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace); + newDebug.log = this.log; + return newDebug; + } + + /** + * Enables a debug mode by namespaces. This can include modes + * separated by a colon and wildcards. + * + * @param {String} namespaces + * @api public + */ + function enable(namespaces) { + createDebug.save(namespaces); + + createDebug.names = []; + createDebug.skips = []; + + let i; + const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/); + const len = split.length; + + for (i = 0; i < len; i++) { + if (!split[i]) { + // ignore empty strings + continue; + } + + namespaces = split[i].replace(/\*/g, '.*?'); + + if (namespaces[0] === '-') { + createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$')); + } else { + createDebug.names.push(new RegExp('^' + namespaces + '$')); + } + } + } + + /** + * Disable debug output. + * + * @return {String} namespaces + * @api public + */ + function disable() { + const namespaces = [ + ...createDebug.names.map(toNamespace), + ...createDebug.skips.map(toNamespace).map(namespace => '-' + namespace) + ].join(','); + createDebug.enable(''); + return namespaces; + } + + /** + * Returns true if the given mode name is enabled, false otherwise. + * + * @param {String} name + * @return {Boolean} + * @api public + */ + function enabled(name) { + if (name[name.length - 1] === '*') { + return true; + } + + let i; + let len; + + for (i = 0, len = createDebug.skips.length; i < len; i++) { + if (createDebug.skips[i].test(name)) { + return false; + } + } + + for (i = 0, len = createDebug.names.length; i < len; i++) { + if (createDebug.names[i].test(name)) { + return true; + } + } + + return false; + } + + /** + * Convert regexp to namespace + * + * @param {RegExp} regxep + * @return {String} namespace + * @api private + */ + function toNamespace(regexp) { + return regexp.toString() + .substring(2, regexp.toString().length - 2) + .replace(/\.\*\?$/, '*'); + } + + /** + * Coerce `val`. + * + * @param {Mixed} val + * @return {Mixed} + * @api private + */ + function coerce(val) { + if (val instanceof Error) { + return val.stack || val.message; + } + return val; + } + + /** + * XXX DO NOT USE. This is a temporary stub function. + * XXX It WILL be removed in the next major release. + */ + function destroy() { + console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.'); + } + + createDebug.enable(createDebug.load()); + + return createDebug; +} + +module.exports = setup; diff --git a/node_modules/debug/src/index.js b/node_modules/debug/src/index.js new file mode 100644 index 0000000..bf4c57f --- /dev/null +++ b/node_modules/debug/src/index.js @@ -0,0 +1,10 @@ +/** + * Detect Electron renderer / nwjs process, which is node, but we should + * treat as a browser. + */ + +if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) { + module.exports = require('./browser.js'); +} else { + module.exports = require('./node.js'); +} diff --git a/node_modules/debug/src/node.js b/node_modules/debug/src/node.js new file mode 100644 index 0000000..79bc085 --- /dev/null +++ b/node_modules/debug/src/node.js @@ -0,0 +1,263 @@ +/** + * Module dependencies. + */ + +const tty = require('tty'); +const util = require('util'); + +/** + * This is the Node.js implementation of `debug()`. + */ + +exports.init = init; +exports.log = log; +exports.formatArgs = formatArgs; +exports.save = save; +exports.load = load; +exports.useColors = useColors; +exports.destroy = util.deprecate( + () => {}, + 'Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.' +); + +/** + * Colors. + */ + +exports.colors = [6, 2, 3, 4, 5, 1]; + +try { + // Optional dependency (as in, doesn't need to be installed, NOT like optionalDependencies in package.json) + // eslint-disable-next-line import/no-extraneous-dependencies + const supportsColor = require('supports-color'); + + if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) { + exports.colors = [ + 20, + 21, + 26, + 27, + 32, + 33, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 56, + 57, + 62, + 63, + 68, + 69, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 92, + 93, + 98, + 99, + 112, + 113, + 128, + 129, + 134, + 135, + 148, + 149, + 160, + 161, + 162, + 163, + 164, + 165, + 166, + 167, + 168, + 169, + 170, + 171, + 172, + 173, + 178, + 179, + 184, + 185, + 196, + 197, + 198, + 199, + 200, + 201, + 202, + 203, + 204, + 205, + 206, + 207, + 208, + 209, + 214, + 215, + 220, + 221 + ]; + } +} catch (error) { + // Swallow - we only care if `supports-color` is available; it doesn't have to be. +} + +/** + * Build up the default `inspectOpts` object from the environment variables. + * + * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js + */ + +exports.inspectOpts = Object.keys(process.env).filter(key => { + return /^debug_/i.test(key); +}).reduce((obj, key) => { + // Camel-case + const prop = key + .substring(6) + .toLowerCase() + .replace(/_([a-z])/g, (_, k) => { + return k.toUpperCase(); + }); + + // Coerce string value into JS value + let val = process.env[key]; + if (/^(yes|on|true|enabled)$/i.test(val)) { + val = true; + } else if (/^(no|off|false|disabled)$/i.test(val)) { + val = false; + } else if (val === 'null') { + val = null; + } else { + val = Number(val); + } + + obj[prop] = val; + return obj; +}, {}); + +/** + * Is stdout a TTY? Colored output is enabled when `true`. + */ + +function useColors() { + return 'colors' in exports.inspectOpts ? + Boolean(exports.inspectOpts.colors) : + tty.isatty(process.stderr.fd); +} + +/** + * Adds ANSI color escape codes if enabled. + * + * @api public + */ + +function formatArgs(args) { + const {namespace: name, useColors} = this; + + if (useColors) { + const c = this.color; + const colorCode = '\u001B[3' + (c < 8 ? c : '8;5;' + c); + const prefix = ` ${colorCode};1m${name} \u001B[0m`; + + args[0] = prefix + args[0].split('\n').join('\n' + prefix); + args.push(colorCode + 'm+' + module.exports.humanize(this.diff) + '\u001B[0m'); + } else { + args[0] = getDate() + name + ' ' + args[0]; + } +} + +function getDate() { + if (exports.inspectOpts.hideDate) { + return ''; + } + return new Date().toISOString() + ' '; +} + +/** + * Invokes `util.format()` with the specified arguments and writes to stderr. + */ + +function log(...args) { + return process.stderr.write(util.format(...args) + '\n'); +} + +/** + * Save `namespaces`. + * + * @param {String} namespaces + * @api private + */ +function save(namespaces) { + if (namespaces) { + process.env.DEBUG = namespaces; + } else { + // If you set a process.env field to null or undefined, it gets cast to the + // string 'null' or 'undefined'. Just delete instead. + delete process.env.DEBUG; + } +} + +/** + * Load `namespaces`. + * + * @return {String} returns the previously persisted debug modes + * @api private + */ + +function load() { + return process.env.DEBUG; +} + +/** + * Init logic for `debug` instances. + * + * Create a new `inspectOpts` object in case `useColors` is set + * differently for a particular `debug` instance. + */ + +function init(debug) { + debug.inspectOpts = {}; + + const keys = Object.keys(exports.inspectOpts); + for (let i = 0; i < keys.length; i++) { + debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]]; + } +} + +module.exports = require('./common')(exports); + +const {formatters} = module.exports; + +/** + * Map %o to `util.inspect()`, all on a single line. + */ + +formatters.o = function (v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts) + .split('\n') + .map(str => str.trim()) + .join(' '); +}; + +/** + * Map %O to `util.inspect()`, allowing multiple lines if needed. + */ + +formatters.O = function (v) { + this.inspectOpts.colors = this.useColors; + return util.inspect(v, this.inspectOpts); +}; diff --git a/node_modules/ecdsa-sig-formatter/CODEOWNERS b/node_modules/ecdsa-sig-formatter/CODEOWNERS new file mode 100644 index 0000000..4451d3d --- /dev/null +++ b/node_modules/ecdsa-sig-formatter/CODEOWNERS @@ -0,0 +1 @@ +* @omsmith diff --git a/node_modules/ecdsa-sig-formatter/LICENSE b/node_modules/ecdsa-sig-formatter/LICENSE new file mode 100644 index 0000000..8754ed6 --- /dev/null +++ b/node_modules/ecdsa-sig-formatter/LICENSE @@ -0,0 +1,201 @@ +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 2015 D2L Corporation + + 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/node_modules/ecdsa-sig-formatter/README.md b/node_modules/ecdsa-sig-formatter/README.md new file mode 100644 index 0000000..daa95d6 --- /dev/null +++ b/node_modules/ecdsa-sig-formatter/README.md @@ -0,0 +1,65 @@ +# ecdsa-sig-formatter + +[![Build Status](https://travis-ci.org/Brightspace/node-ecdsa-sig-formatter.svg?branch=master)](https://travis-ci.org/Brightspace/node-ecdsa-sig-formatter) [![Coverage Status](https://coveralls.io/repos/Brightspace/node-ecdsa-sig-formatter/badge.svg)](https://coveralls.io/r/Brightspace/node-ecdsa-sig-formatter) + +Translate between JOSE and ASN.1/DER encodings for ECDSA signatures + +## Install +```sh +npm install ecdsa-sig-formatter --save +``` + +## Usage +```js +var format = require('ecdsa-sig-formatter'); + +var derSignature = '..'; // asn.1/DER encoded ecdsa signature + +var joseSignature = format.derToJose(derSignature); + +``` + +### API + +--- + +#### `.derToJose(Buffer|String signature, String alg)` -> `String` + +Convert the ASN.1/DER encoded signature to a JOSE-style concatenated signature. +Returns a _base64 url_ encoded `String`. + +* If _signature_ is a `String`, it should be _base64_ encoded +* _alg_ must be one of _ES256_, _ES384_ or _ES512_ + +--- + +#### `.joseToDer(Buffer|String signature, String alg)` -> `Buffer` + +Convert the JOSE-style concatenated signature to an ASN.1/DER encoded +signature. Returns a `Buffer` + +* If _signature_ is a `String`, it should be _base64 url_ encoded +* _alg_ must be one of _ES256_, _ES384_ or _ES512_ + +## Contributing + +1. **Fork** the repository. Committing directly against this repository is + highly discouraged. + +2. Make your modifications in a branch, updating and writing new unit tests + as necessary in the `spec` directory. + +3. Ensure that all tests pass with `npm test` + +4. `rebase` your changes against master. *Do not merge*. + +5. Submit a pull request to this repository. Wait for tests to run and someone + to chime in. + +### Code Style + +This repository is configured with [EditorConfig][EditorConfig] and +[ESLint][ESLint] rules. + +[EditorConfig]: http://editorconfig.org/ +[ESLint]: http://eslint.org diff --git a/node_modules/ecdsa-sig-formatter/package.json b/node_modules/ecdsa-sig-formatter/package.json new file mode 100644 index 0000000..5526a3b --- /dev/null +++ b/node_modules/ecdsa-sig-formatter/package.json @@ -0,0 +1,73 @@ +{ + "_from": "ecdsa-sig-formatter@1.0.11", + "_id": "ecdsa-sig-formatter@1.0.11", + "_inBundle": false, + "_integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "_location": "/ecdsa-sig-formatter", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "ecdsa-sig-formatter@1.0.11", + "name": "ecdsa-sig-formatter", + "escapedName": "ecdsa-sig-formatter", + "rawSpec": "1.0.11", + "saveSpec": null, + "fetchSpec": "1.0.11" + }, + "_requiredBy": [ + "/jwa" + ], + "_resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "_shasum": "ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf", + "_spec": "ecdsa-sig-formatter@1.0.11", + "_where": "D:\\Users\\user\\Documents\\Portofolio\\Github\\WebsiteFootballPWA\\node_modules\\jwa", + "author": { + "name": "D2L Corporation" + }, + "bugs": { + "url": "https://github.com/Brightspace/node-ecdsa-sig-formatter/issues" + }, + "bundleDependencies": false, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "deprecated": false, + "description": "Translate ECDSA signatures between ASN.1/DER and JOSE-style concatenation", + "devDependencies": { + "bench": "^0.3.6", + "chai": "^3.5.0", + "coveralls": "^2.11.9", + "eslint": "^2.12.0", + "eslint-config-brightspace": "^0.2.1", + "istanbul": "^0.4.3", + "jwk-to-pem": "^1.2.5", + "mocha": "^2.5.3", + "native-crypto": "^1.7.0" + }, + "homepage": "https://github.com/Brightspace/node-ecdsa-sig-formatter#readme", + "keywords": [ + "ecdsa", + "der", + "asn.1", + "jwt", + "jwa", + "jsonwebtoken", + "jose" + ], + "license": "Apache-2.0", + "main": "src/ecdsa-sig-formatter.js", + "name": "ecdsa-sig-formatter", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/Brightspace/node-ecdsa-sig-formatter.git" + }, + "scripts": { + "check-style": "eslint .", + "pretest": "npm run check-style", + "report-cov": "cat ./coverage/lcov.info | coveralls", + "test": "istanbul cover --root src _mocha -- spec" + }, + "typings": "./src/ecdsa-sig-formatter.d.ts", + "version": "1.0.11" +} diff --git a/node_modules/ecdsa-sig-formatter/src/ecdsa-sig-formatter.d.ts b/node_modules/ecdsa-sig-formatter/src/ecdsa-sig-formatter.d.ts new file mode 100644 index 0000000..9693aa0 --- /dev/null +++ b/node_modules/ecdsa-sig-formatter/src/ecdsa-sig-formatter.d.ts @@ -0,0 +1,17 @@ +/// + +declare module "ecdsa-sig-formatter" { + /** + * Convert the ASN.1/DER encoded signature to a JOSE-style concatenated signature. Returns a base64 url encoded String. + * If signature is a String, it should be base64 encoded + * alg must be one of ES256, ES384 or ES512 + */ + export function derToJose(signature: Buffer | string, alg: string): string; + + /** + * Convert the JOSE-style concatenated signature to an ASN.1/DER encoded signature. Returns a Buffer + * If signature is a String, it should be base64 url encoded + * alg must be one of ES256, ES384 or ES512 + */ + export function joseToDer(signature: Buffer | string, alg: string): Buffer +} diff --git a/node_modules/ecdsa-sig-formatter/src/ecdsa-sig-formatter.js b/node_modules/ecdsa-sig-formatter/src/ecdsa-sig-formatter.js new file mode 100644 index 0000000..38eeb9b --- /dev/null +++ b/node_modules/ecdsa-sig-formatter/src/ecdsa-sig-formatter.js @@ -0,0 +1,187 @@ +'use strict'; + +var Buffer = require('safe-buffer').Buffer; + +var getParamBytesForAlg = require('./param-bytes-for-alg'); + +var MAX_OCTET = 0x80, + CLASS_UNIVERSAL = 0, + PRIMITIVE_BIT = 0x20, + TAG_SEQ = 0x10, + TAG_INT = 0x02, + ENCODED_TAG_SEQ = (TAG_SEQ | PRIMITIVE_BIT) | (CLASS_UNIVERSAL << 6), + ENCODED_TAG_INT = TAG_INT | (CLASS_UNIVERSAL << 6); + +function base64Url(base64) { + return base64 + .replace(/=/g, '') + .replace(/\+/g, '-') + .replace(/\//g, '_'); +} + +function signatureAsBuffer(signature) { + if (Buffer.isBuffer(signature)) { + return signature; + } else if ('string' === typeof signature) { + return Buffer.from(signature, 'base64'); + } + + throw new TypeError('ECDSA signature must be a Base64 string or a Buffer'); +} + +function derToJose(signature, alg) { + signature = signatureAsBuffer(signature); + var paramBytes = getParamBytesForAlg(alg); + + // the DER encoded param should at most be the param size, plus a padding + // zero, since due to being a signed integer + var maxEncodedParamLength = paramBytes + 1; + + var inputLength = signature.length; + + var offset = 0; + if (signature[offset++] !== ENCODED_TAG_SEQ) { + throw new Error('Could not find expected "seq"'); + } + + var seqLength = signature[offset++]; + if (seqLength === (MAX_OCTET | 1)) { + seqLength = signature[offset++]; + } + + if (inputLength - offset < seqLength) { + throw new Error('"seq" specified length of "' + seqLength + '", only "' + (inputLength - offset) + '" remaining'); + } + + if (signature[offset++] !== ENCODED_TAG_INT) { + throw new Error('Could not find expected "int" for "r"'); + } + + var rLength = signature[offset++]; + + if (inputLength - offset - 2 < rLength) { + throw new Error('"r" specified length of "' + rLength + '", only "' + (inputLength - offset - 2) + '" available'); + } + + if (maxEncodedParamLength < rLength) { + throw new Error('"r" specified length of "' + rLength + '", max of "' + maxEncodedParamLength + '" is acceptable'); + } + + var rOffset = offset; + offset += rLength; + + if (signature[offset++] !== ENCODED_TAG_INT) { + throw new Error('Could not find expected "int" for "s"'); + } + + var sLength = signature[offset++]; + + if (inputLength - offset !== sLength) { + throw new Error('"s" specified length of "' + sLength + '", expected "' + (inputLength - offset) + '"'); + } + + if (maxEncodedParamLength < sLength) { + throw new Error('"s" specified length of "' + sLength + '", max of "' + maxEncodedParamLength + '" is acceptable'); + } + + var sOffset = offset; + offset += sLength; + + if (offset !== inputLength) { + throw new Error('Expected to consume entire buffer, but "' + (inputLength - offset) + '" bytes remain'); + } + + var rPadding = paramBytes - rLength, + sPadding = paramBytes - sLength; + + var dst = Buffer.allocUnsafe(rPadding + rLength + sPadding + sLength); + + for (offset = 0; offset < rPadding; ++offset) { + dst[offset] = 0; + } + signature.copy(dst, offset, rOffset + Math.max(-rPadding, 0), rOffset + rLength); + + offset = paramBytes; + + for (var o = offset; offset < o + sPadding; ++offset) { + dst[offset] = 0; + } + signature.copy(dst, offset, sOffset + Math.max(-sPadding, 0), sOffset + sLength); + + dst = dst.toString('base64'); + dst = base64Url(dst); + + return dst; +} + +function countPadding(buf, start, stop) { + var padding = 0; + while (start + padding < stop && buf[start + padding] === 0) { + ++padding; + } + + var needsSign = buf[start + padding] >= MAX_OCTET; + if (needsSign) { + --padding; + } + + return padding; +} + +function joseToDer(signature, alg) { + signature = signatureAsBuffer(signature); + var paramBytes = getParamBytesForAlg(alg); + + var signatureBytes = signature.length; + if (signatureBytes !== paramBytes * 2) { + throw new TypeError('"' + alg + '" signatures must be "' + paramBytes * 2 + '" bytes, saw "' + signatureBytes + '"'); + } + + var rPadding = countPadding(signature, 0, paramBytes); + var sPadding = countPadding(signature, paramBytes, signature.length); + var rLength = paramBytes - rPadding; + var sLength = paramBytes - sPadding; + + var rsBytes = 1 + 1 + rLength + 1 + 1 + sLength; + + var shortLength = rsBytes < MAX_OCTET; + + var dst = Buffer.allocUnsafe((shortLength ? 2 : 3) + rsBytes); + + var offset = 0; + dst[offset++] = ENCODED_TAG_SEQ; + if (shortLength) { + // Bit 8 has value "0" + // bits 7-1 give the length. + dst[offset++] = rsBytes; + } else { + // Bit 8 of first octet has value "1" + // bits 7-1 give the number of additional length octets. + dst[offset++] = MAX_OCTET | 1; + // length, base 256 + dst[offset++] = rsBytes & 0xff; + } + dst[offset++] = ENCODED_TAG_INT; + dst[offset++] = rLength; + if (rPadding < 0) { + dst[offset++] = 0; + offset += signature.copy(dst, offset, 0, paramBytes); + } else { + offset += signature.copy(dst, offset, rPadding, paramBytes); + } + dst[offset++] = ENCODED_TAG_INT; + dst[offset++] = sLength; + if (sPadding < 0) { + dst[offset++] = 0; + signature.copy(dst, offset, paramBytes); + } else { + signature.copy(dst, offset, paramBytes + sPadding); + } + + return dst; +} + +module.exports = { + derToJose: derToJose, + joseToDer: joseToDer +}; diff --git a/node_modules/ecdsa-sig-formatter/src/param-bytes-for-alg.js b/node_modules/ecdsa-sig-formatter/src/param-bytes-for-alg.js new file mode 100644 index 0000000..9fe67ac --- /dev/null +++ b/node_modules/ecdsa-sig-formatter/src/param-bytes-for-alg.js @@ -0,0 +1,23 @@ +'use strict'; + +function getParamSize(keySize) { + var result = ((keySize / 8) | 0) + (keySize % 8 === 0 ? 0 : 1); + return result; +} + +var paramBytesForAlg = { + ES256: getParamSize(256), + ES384: getParamSize(384), + ES512: getParamSize(521) +}; + +function getParamBytesForAlg(alg) { + var paramBytes = paramBytesForAlg[alg]; + if (paramBytes) { + return paramBytes; + } + + throw new Error('Unknown algorithm "' + alg + '"'); +} + +module.exports = getParamBytesForAlg; diff --git a/node_modules/http_ece/README.md b/node_modules/http_ece/README.md new file mode 100644 index 0000000..80e7dd4 --- /dev/null +++ b/node_modules/http_ece/README.md @@ -0,0 +1,28 @@ +# encrypted-content-encoding + +A simple implementation of the [HTTP encrypted +content-encoding](https://tools.ietf.org/html/rfc8188) + +# Use + +```js +var ece = require('http_ece'); +var crypto = require('crypto') +var base64 = require('base64url'); + +var parameters = { + key: base64.encode(crypto.randomBytes(16)), + salt: base64.encode(crypto.randomBytes(16)) +}; +var encrypted = ece.encrypt(data, parameters); + +var decrypted = ece.decrypt(encrypted, parameters); + +require('assert').equal(decrypted.compare(data), 0); +``` + +This also supports the static-ephemeral ECDH mode. The source explains how. + +# TODO + +Use the node streams API instead of the legacy APIs. diff --git a/node_modules/http_ece/ece.js b/node_modules/http_ece/ece.js new file mode 100644 index 0000000..3c73bdc --- /dev/null +++ b/node_modules/http_ece/ece.js @@ -0,0 +1,522 @@ +'use strict'; +/* + * Encrypted content coding + * + * === Note about versions === + * + * This code supports multiple versions of the draft. This is selected using + * the |version| parameter. + * + * aes128gcm: The most recent version, the salt, record size and key identifier + * are included in a header that is part of the encrypted content coding. + * + * aesgcm: The version that is widely deployed with WebPush (as of 2016-11). + * This version is selected by default, unless you specify a |padSize| of 1. + * + * aesgcm128: This version is old and will be removed in an upcoming release. + * This version is selected by providing a |padSize| parameter of 1. + */ + +var crypto = require('crypto'); +var base64 = require('urlsafe-base64'); + +var AES_GCM = 'aes-128-gcm'; +var PAD_SIZE = { 'aes128gcm': 1, 'aesgcm': 2, 'aesgcm128': 1 }; +var TAG_LENGTH = 16; +var KEY_LENGTH = 16; +var NONCE_LENGTH = 12; +var SHA_256_LENGTH = 32; +var MODE_ENCRYPT = 'encrypt'; +var MODE_DECRYPT = 'decrypt'; + +var keylog; +if (process.env.ECE_KEYLOG === '1') { + keylog = function(m, k) { + console.warn(m + ' [' + k.length + ']: ' + base64.encode(k)); + return k; + }; +} else { + keylog = function(m, k) { return k; }; +} + +/* Optionally base64 decode something. */ +function decode(b) { + if (typeof b === 'string') { + return base64.decode(b); + } + return b; +} + +function HMAC_hash(key, input) { + var hmac = crypto.createHmac('sha256', key); + hmac.update(input); + return hmac.digest(); +} + +/* HKDF as defined in RFC5869, using SHA-256 */ +function HKDF_extract(salt, ikm) { + keylog('salt', salt); + keylog('ikm', ikm); + return keylog('extract', HMAC_hash(salt, ikm)); +} + +function HKDF_expand(prk, info, l) { + keylog('prk', prk); + keylog('info', info); + var output = new Buffer(0); + var T = new Buffer(0); + info = new Buffer(info, 'ascii'); + var counter = 0; + var cbuf = new Buffer(1); + while (output.length < l) { + cbuf.writeUIntBE(++counter, 0, 1); + T = HMAC_hash(prk, Buffer.concat([T, info, cbuf])); + output = Buffer.concat([output, T]); + } + + return keylog('expand', output.slice(0, l)); +} + +function HKDF(salt, ikm, info, len) { + return HKDF_expand(HKDF_extract(salt, ikm), info, len); +} + +function info(base, context) { + var result = Buffer.concat([ + new Buffer('Content-Encoding: ' + base + '\0', 'ascii'), + context + ]); + keylog('info ' + base, result); + return result; +} + +function lengthPrefix(buffer) { + var b = Buffer.concat([new Buffer(2), buffer]); + b.writeUIntBE(buffer.length, 0, 2); + return b; +} + +function extractDH(header, mode) { + var key = header.privateKey; + var senderPubKey, receiverPubKey; + if (mode === MODE_ENCRYPT) { + senderPubKey = key.getPublicKey(); + receiverPubKey = header.dh; + } else if (mode === MODE_DECRYPT) { + senderPubKey = header.dh; + receiverPubKey = key.getPublicKey(); + } else { + throw new Error('Unknown mode only ' + MODE_ENCRYPT + + ' and ' + MODE_DECRYPT + ' supported'); + } + return { + secret: key.computeSecret(header.dh), + context: Buffer.concat([ + Buffer.from(header.keylabel, 'ascii'), + Buffer.from([0]), + lengthPrefix(receiverPubKey), // user agent + lengthPrefix(senderPubKey) // application server + ]) + }; +} + +function extractSecretAndContext(header, mode) { + var result = { secret: null, context: new Buffer(0) }; + if (header.key) { + result.secret = header.key; + if (result.secret.length !== KEY_LENGTH) { + throw new Error('An explicit key must be ' + KEY_LENGTH + ' bytes'); + } + } else if (header.dh) { // receiver/decrypt + result = extractDH(header, mode); + } else if (typeof header.keyid !== undefined) { + result.secret = header.keymap[header.keyid]; + } + if (!result.secret) { + throw new Error('Unable to determine key'); + } + keylog('secret', result.secret); + keylog('context', result.context); + if (header.authSecret) { + result.secret = HKDF(header.authSecret, result.secret, + info('auth', new Buffer(0)), SHA_256_LENGTH); + keylog('authsecret', result.secret); + } + return result; +} + +function webpushSecret(header, mode) { + if (!header.authSecret) { + throw new Error('No authentication secret for webpush'); + } + keylog('authsecret', header.authSecret); + + var remotePubKey, senderPubKey, receiverPubKey; + if (mode === MODE_ENCRYPT) { + senderPubKey = header.privateKey.getPublicKey(); + remotePubKey = receiverPubKey = header.dh; + } else if (mode === MODE_DECRYPT) { + remotePubKey = senderPubKey = header.keyid; + receiverPubKey = header.privateKey.getPublicKey(); + } else { + throw new Error('Unknown mode only ' + MODE_ENCRYPT + + ' and ' + MODE_DECRYPT + ' supported'); + } + keylog('remote pubkey', remotePubKey); + keylog('sender pubkey', senderPubKey); + keylog('receiver pubkey', receiverPubKey); + return keylog('secret dh', + HKDF(header.authSecret, + header.privateKey.computeSecret(remotePubKey), + Buffer.concat([ + Buffer.from('WebPush: info\0'), + receiverPubKey, + senderPubKey + ]), + SHA_256_LENGTH)); +} + +function extractSecret(header, mode) { + if (header.key) { + if (header.key.length !== KEY_LENGTH) { + throw new Error('An explicit key must be ' + KEY_LENGTH + ' bytes'); + } + return keylog('secret key', header.key); + } + + if (!header.privateKey) { + // Lookup based on keyid + var key = header.keymap && header.keymap[header.keyid]; + if (!key) { + throw new Error('No saved key (keyid: "' + header.keyid + '")'); + } + return key; + } + + return webpushSecret(header, mode); +} + +function deriveKeyAndNonce(header, mode) { + if (!header.salt) { + throw new Error('must include a salt parameter for ' + header.version); + } + var keyInfo; + var nonceInfo; + var secret; + if (header.version === 'aesgcm128') { + // really old + keyInfo = 'Content-Encoding: aesgcm128'; + nonceInfo = 'Content-Encoding: nonce'; + secret = extractSecretAndContext(header, mode).secret; + } else if (header.version === 'aesgcm') { + // old + var s = extractSecretAndContext(header, mode); + keyInfo = info('aesgcm', s.context); + nonceInfo = info('nonce', s.context); + secret = s.secret; + } else if (header.version === 'aes128gcm') { + // latest + keyInfo = Buffer.from('Content-Encoding: aes128gcm\0'); + nonceInfo = Buffer.from('Content-Encoding: nonce\0'); + secret = extractSecret(header, mode); + } else { + throw new Error('Unable to set context for mode ' + params.version); + } + var prk = HKDF_extract(header.salt, secret); + var result = { + key: HKDF_expand(prk, keyInfo, KEY_LENGTH), + nonce: HKDF_expand(prk, nonceInfo, NONCE_LENGTH) + }; + keylog('key', result.key); + keylog('nonce base', result.nonce); + return result; +} + +/* Parse command-line arguments. */ +function parseParams(params) { + var header = {}; + + header.version = params.version || 'aes128gcm'; + header.rs = parseInt(params.rs, 10); + if (isNaN(header.rs)) { + header.rs = 4096; + } + var overhead = PAD_SIZE[header.version]; + if (header.version === 'aes128gcm') { + overhead += TAG_LENGTH; + } + if (header.rs <= overhead) { + throw new Error('The rs parameter has to be greater than ' + overhead); + } + + if (params.salt) { + header.salt = decode(params.salt); + if (header.salt.length !== KEY_LENGTH) { + throw new Error('The salt parameter must be ' + KEY_LENGTH + ' bytes'); + } + } + header.keyid = params.keyid; + if (params.key) { + header.key = decode(params.key); + } else { + header.privateKey = params.privateKey; + if (!header.privateKey) { + header.keymap = params.keymap; + } + if (header.version !== 'aes128gcm') { + header.keylabel = params.keylabel || 'P-256'; + } + if (params.dh) { + header.dh = decode(params.dh); + } + } + if (params.authSecret) { + header.authSecret = decode(params.authSecret); + } + return header; +} + +function generateNonce(base, counter) { + var nonce = new Buffer(base); + var m = nonce.readUIntBE(nonce.length - 6, 6); + var x = ((m ^ counter) & 0xffffff) + + ((((m / 0x1000000) ^ (counter / 0x1000000)) & 0xffffff) * 0x1000000); + nonce.writeUIntBE(x, nonce.length - 6, 6); + keylog('nonce' + counter, nonce); + return nonce; +} + +/* Used when decrypting aes128gcm to populate the header values. Modifies the + * header values in place and returns the size of the header. */ +function readHeader(buffer, header) { + var idsz = buffer.readUIntBE(20, 1); + header.salt = buffer.slice(0, KEY_LENGTH); + header.rs = buffer.readUIntBE(KEY_LENGTH, 4); + header.keyid = buffer.slice(21, 21 + idsz); + return 21 + idsz; +} + +function unpadLegacy(data, version) { + var padSize = PAD_SIZE[version]; + var pad = data.readUIntBE(0, padSize); + if (pad + padSize > data.length) { + throw new Error('padding exceeds block size'); + } + keylog('padding', data.slice(0, padSize + pad)); + var padCheck = new Buffer(pad); + padCheck.fill(0); + if (padCheck.compare(data.slice(padSize, padSize + pad)) !== 0) { + throw new Error('invalid padding'); + } + return data.slice(padSize + pad); +} + +function unpad(data, last) { + var i = data.length - 1; + while(i >= 0) { + if (data[i]) { + if (last) { + if (data[i] !== 2) { + throw new Error('last record needs to start padding with a 2'); + } + } else { + if (data[i] !== 1) { + throw new Error('last record needs to start padding with a 2'); + } + } + return data.slice(0, i); + } + --i; + } + throw new Error('all zero plaintext'); +} + +function decryptRecord(key, counter, buffer, header, last) { + keylog('decrypt', buffer); + var nonce = generateNonce(key.nonce, counter); + var gcm = crypto.createDecipheriv(AES_GCM, key.key, nonce); + gcm.setAuthTag(buffer.slice(buffer.length - TAG_LENGTH)); + var data = gcm.update(buffer.slice(0, buffer.length - TAG_LENGTH)); + data = Buffer.concat([data, gcm.final()]); + keylog('decrypted', data); + if (header.version !== 'aes128gcm') { + return unpadLegacy(data, header.version); + } + return unpad(data, last); +} + +/** + * Decrypt some bytes. This uses the parameters to determine the key and block + * size, which are described in the draft. Binary values are base64url encoded. + * + * |params.version| contains the version of encoding to use: aes128gcm is the latest, + * but aesgcm and aesgcm128 are also accepted (though the latter two might + * disappear in a future release). If omitted, assume aes128gcm. + * + * If |params.key| is specified, that value is used as the key. + * + * If the version is aes128gcm, the keyid is extracted from the header and used + * as the ECDH public key of the sender. For version aesgcm and aesgcm128, + * |params.dh| needs to be provided with the public key of the sender. + * + * The |params.privateKey| includes the private key of the receiver. + */ +function decrypt(buffer, params) { + var header = parseParams(params); + if (header.version === 'aes128gcm') { + var headerLength = readHeader(buffer, header); + buffer = buffer.slice(headerLength); + } + var key = deriveKeyAndNonce(header, MODE_DECRYPT); + var start = 0; + var result = new Buffer(0); + + var chunkSize = header.rs; + if (header.version !== 'aes128gcm') { + chunkSize += TAG_LENGTH; + } + + for (var i = 0; start < buffer.length; ++i) { + var end = start + chunkSize; + if (header.version !== 'aes128gcm' && end === buffer.length) { + throw new Error('Truncated payload'); + } + end = Math.min(end, buffer.length); + if (end - start <= TAG_LENGTH) { + throw new Error('Invalid block: too small at ' + i); + } + var block = decryptRecord(key, i, buffer.slice(start, end), + header, end >= buffer.length); + result = Buffer.concat([result, block]); + start = end; + } + return result; +} + +function encryptRecord(key, counter, buffer, pad, header, last) { + keylog('encrypt', buffer); + pad = pad || 0; + var nonce = generateNonce(key.nonce, counter); + var gcm = crypto.createCipheriv(AES_GCM, key.key, nonce); + + var ciphertext = []; + var padSize = PAD_SIZE[header.version]; + var padding = new Buffer(pad + padSize); + padding.fill(0); + + if (header.version !== 'aes128gcm') { + padding.writeUIntBE(pad, 0, padSize); + keylog('padding', padding); + ciphertext.push(gcm.update(padding)); + ciphertext.push(gcm.update(buffer)); + + if (!last && padding.length + buffer.length < header.rs) { + throw new Error('Unable to pad to record size'); + } + } else { + ciphertext.push(gcm.update(buffer)); + padding.writeUIntBE(last ? 2 : 1, 0, 1); + keylog('padding', padding); + ciphertext.push(gcm.update(padding)); + } + + gcm.final(); + var tag = gcm.getAuthTag(); + if (tag.length !== TAG_LENGTH) { + throw new Error('invalid tag generated'); + } + ciphertext.push(tag); + return keylog('encrypted', Buffer.concat(ciphertext)); +} + +function writeHeader(header) { + var ints = new Buffer(5); + var keyid = Buffer.from(header.keyid || []); + if (keyid.length > 255) { + throw new Error('keyid is too large'); + } + ints.writeUIntBE(header.rs, 0, 4); + ints.writeUIntBE(keyid.length, 4, 1); + return Buffer.concat([header.salt, ints, keyid]); +} + +/** + * Encrypt some bytes. This uses the parameters to determine the key and block + * size, which are described in the draft. + * + * |params.version| contains the version of encoding to use: aes128gcm is the latest, + * but aesgcm and aesgcm128 are also accepted (though the latter two might + * disappear in a future release). If omitted, assume aes128gcm. + * + * If |params.key| is specified, that value is used as the key. + * + * For Diffie-Hellman (WebPush), |params.dh| includes the public key of the + * receiver. |params.privateKey| is used to establish a shared secret. Key + * pairs can be created using |crypto.createECDH()|. + */ +function encrypt(buffer, params) { + if (!Buffer.isBuffer(buffer)) { + throw new Error('buffer argument must be a Buffer'); + } + var header = parseParams(params); + if (!header.salt) { + header.salt = crypto.randomBytes(KEY_LENGTH); + } + + var result; + if (header.version === 'aes128gcm') { + // Save the DH public key in the header unless keyid is set. + if (header.privateKey && !header.keyid) { + header.keyid = header.privateKey.getPublicKey(); + } + result = writeHeader(header); + } else { + // No header on other versions + result = new Buffer(0); + } + + var key = deriveKeyAndNonce(header, MODE_ENCRYPT); + var start = 0; + var padSize = PAD_SIZE[header.version]; + var overhead = padSize; + if (header.version === 'aes128gcm') { + overhead += TAG_LENGTH; + } + var pad = isNaN(parseInt(params.pad, 10)) ? 0 : parseInt(params.pad, 10); + + var counter = 0; + var last = false; + while (!last) { + // Pad so that at least one data byte is in a block. + var recordPad = Math.min(header.rs - overhead - 1, pad); + if (header.version !== 'aes128gcm') { + recordPad = Math.min((1 << (padSize * 8)) - 1, recordPad); + } + if (pad > 0 && recordPad === 0) { + ++recordPad; // Deal with perverse case of rs=overhead+1 with padding. + } + pad -= recordPad; + + var end = start + header.rs - overhead - recordPad; + if (header.version !== 'aes128gcm') { + // The > here ensures that we write out a padding-only block at the end + // of a buffer. + last = end > buffer.length; + } else { + last = end >= buffer.length; + } + last = last && pad <= 0; + var block = encryptRecord(key, counter, buffer.slice(start, end), + recordPad, header, last); + result = Buffer.concat([result, block]); + + start = end; + ++counter; + } + return result; +} + +module.exports = { + decrypt: decrypt, + encrypt: encrypt +}; diff --git a/node_modules/http_ece/package.json b/node_modules/http_ece/package.json new file mode 100644 index 0000000..17e3500 --- /dev/null +++ b/node_modules/http_ece/package.json @@ -0,0 +1,59 @@ +{ + "_from": "http_ece@1.1.0", + "_id": "http_ece@1.1.0", + "_inBundle": false, + "_integrity": "sha512-bptAfCDdPJxOs5zYSe7Y3lpr772s1G346R4Td5LgRUeCwIGpCGDUTJxRrhTNcAXbx37spge0kWEIH7QAYWNTlA==", + "_location": "/http_ece", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "http_ece@1.1.0", + "name": "http_ece", + "escapedName": "http_ece", + "rawSpec": "1.1.0", + "saveSpec": null, + "fetchSpec": "1.1.0" + }, + "_requiredBy": [ + "/web-push" + ], + "_resolved": "https://registry.npmjs.org/http_ece/-/http_ece-1.1.0.tgz", + "_shasum": "74780c6eb32d8ddfe9e36a83abcd81fe0cd4fb75", + "_spec": "http_ece@1.1.0", + "_where": "D:\\Users\\user\\Documents\\Portofolio\\Github\\WebsiteFootballPWA\\node_modules\\web-push", + "author": { + "name": "Martin Thomson", + "email": "martin.thomson@gmail.com" + }, + "bugs": { + "url": "https://github.com/martinthomson/encrypted-content-encoding/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "name": "Marco Castelluccio", + "email": "mcastelluccio@mozilla.com" + } + ], + "dependencies": { + "urlsafe-base64": "~1.0.0" + }, + "deprecated": false, + "description": "Encrypted Content-Encoding for HTTP", + "engines": { + "node": ">=4" + }, + "homepage": "https://github.com/martinthomson/encrypted-content-encoding", + "license": "MIT", + "main": "./ece.js", + "name": "http_ece", + "repository": { + "type": "git", + "url": "git+https://github.com/martinthomson/encrypted-content-encoding.git" + }, + "scripts": { + "test": "node ./test.js" + }, + "version": "1.1.0" +} diff --git a/node_modules/http_ece/package.json~ b/node_modules/http_ece/package.json~ new file mode 100644 index 0000000..941c6a3 --- /dev/null +++ b/node_modules/http_ece/package.json~ @@ -0,0 +1,30 @@ +{ + "name": "http_ece", + "version": "1.0.3", + "description": "Encrypted Content-Encoding for HTTP", + "homepage": "https://github.com/martinthomson/encrypted-content-encoding", + "bugs": "https://github.com/martinthomson/encrypted-content-encoding/issues", + "author": { + "name": "Martin Thomson", + "email": "martin.thomson@gmail.com" + }, + "contributors": [{ + "name": "Marco Castelluccio", + "email": "mcastelluccio@mozilla.com" + }], + "repository": { + "type": "git", + "url": "https://github.com/martinthomson/encrypted-content-encoding.git" + }, + "license": "MIT", + "main": "./ece.js", + "scripts": { + "test": "node ./test.js" + }, + "engines": { + "node": ">=4" + }, + "dependencies": { + "urlsafe-base64": "~1.0.0" + } +} diff --git a/node_modules/http_ece/tmp.js~ b/node_modules/http_ece/tmp.js~ new file mode 100644 index 0000000..ad0319b --- /dev/null +++ b/node_modules/http_ece/tmp.js~ @@ -0,0 +1,36 @@ +'use strict'; +var base64 = require('urlsafe-base64'); +function log(n, x) { + console.log(n, x.length, Buffer.isBuffer(x) ? base64.encode(x) : x); +} + +/*var e = base64.decode('uNCkWiNYzKTnBN9ji3-qWAAAAAoCYTGH' + + 'OqYFz-0in3dpb-VE2GfBngkaPy6bZus_' + + 'qLF79s6zQyTSsA0iLOKyd3JqVIwprNzV' + + 'atRCWZGUx_qsFbJBCQu62RqQuR2d'); */ +var h1 = base64.decode('DGv6ra1nlYgDCS1FRnbzlwAAxowA'); +log('h1', h1); +var dh = base64.decode('BP4z9KsN6nGRTbVYI_c7VJSPQTBtkgcy27mlmlMoZIIgDll6e3vCYLocInmYWAmS6TlzAC8wEqKK6PBru3jl7A8'); +log('dh', dh); +h1.writeUIntBE(dh.length, 20, 1); +var c = base64.decode('Ig1VvoJvrVBFhclGlx4G2FuProCVzJY04Lg5vUP2LeswtWoBGHGoYXUzAwuxQGRGxoNbh8BROK3gmJ0'); +log('c', c); +log('h2', Buffer.concat([h1, dh])); +log('m', Buffer.concat([h1, dh, c])); + +var e = base64.decode('uNCkWiNYzKTnBN9ji3-qWAAAAAoAhzqmBc_tIp93aW_lRNhnwZ4JGj8um2brP6ixe_bOs0Mk0rANIizisndyalSMKazc1WrUQlmRlMf6rBWyQQkLutkakLkdnQ'); + +log('y', e); +log('x', Buffer.concat([base64.decode('uNCkWiNYzKTnBN9ji3-qW'), Buffer.from([0, 0, 0, 10, 2, 'a'.charCodeAt(0), '1'.charCodeAt(0)]), base64.decode('hzqmBc_tIp93aW_lRNhnwZ4JGj8um2brP6g'), base64.decode('sXv2zrNDJNKwDSIs4rJ3cmpUjCms3NVq1EI'), base64.decode('WZGUx_qsFbJBCQu62RqQuR2d') ])); + +var salt = e.slice(0, 16); +log('salt', salt); +var rs = e.readUIntBE(16, 4); +log('rs', rs); +var idsz = e.readUIntBE(20, 1); +var id = e.slice(21, 21 + idsz); +log('id', id); +console.log('id', id.toString()); +log('header', e.slice(0, 21 + idsz)); +log('main', e.slice(21 + idsz, e.length - 16)); +log('tag', e.slice(e.length - 16)); diff --git a/node_modules/https-proxy-agent/README.md b/node_modules/https-proxy-agent/README.md new file mode 100644 index 0000000..328656a --- /dev/null +++ b/node_modules/https-proxy-agent/README.md @@ -0,0 +1,137 @@ +https-proxy-agent +================ +### An HTTP(s) proxy `http.Agent` implementation for HTTPS +[![Build Status](https://github.com/TooTallNate/node-https-proxy-agent/workflows/Node%20CI/badge.svg)](https://github.com/TooTallNate/node-https-proxy-agent/actions?workflow=Node+CI) + +This module provides an `http.Agent` implementation that connects to a specified +HTTP or HTTPS proxy server, and can be used with the built-in `https` module. + +Specifically, this `Agent` implementation connects to an intermediary "proxy" +server and issues the [CONNECT HTTP method][CONNECT], which tells the proxy to +open a direct TCP connection to the destination server. + +Since this agent implements the CONNECT HTTP method, it also works with other +protocols that use this method when connecting over proxies (i.e. WebSockets). +See the "Examples" section below for more. + + +Installation +------------ + +Install with `npm`: + +``` bash +$ npm install https-proxy-agent +``` + + +Examples +-------- + +#### `https` module example + +``` js +var url = require('url'); +var https = require('https'); +var HttpsProxyAgent = require('https-proxy-agent'); + +// HTTP/HTTPS proxy to connect to +var proxy = process.env.http_proxy || 'http://168.63.76.32:3128'; +console.log('using proxy server %j', proxy); + +// HTTPS endpoint for the proxy to connect to +var endpoint = process.argv[2] || 'https://graph.facebook.com/tootallnate'; +console.log('attempting to GET %j', endpoint); +var options = url.parse(endpoint); + +// create an instance of the `HttpsProxyAgent` class with the proxy server information +var agent = new HttpsProxyAgent(proxy); +options.agent = agent; + +https.get(options, function (res) { + console.log('"response" event!', res.headers); + res.pipe(process.stdout); +}); +``` + +#### `ws` WebSocket connection example + +``` js +var url = require('url'); +var WebSocket = require('ws'); +var HttpsProxyAgent = require('https-proxy-agent'); + +// HTTP/HTTPS proxy to connect to +var proxy = process.env.http_proxy || 'http://168.63.76.32:3128'; +console.log('using proxy server %j', proxy); + +// WebSocket endpoint for the proxy to connect to +var endpoint = process.argv[2] || 'ws://echo.websocket.org'; +var parsed = url.parse(endpoint); +console.log('attempting to connect to WebSocket %j', endpoint); + +// create an instance of the `HttpsProxyAgent` class with the proxy server information +var options = url.parse(proxy); + +var agent = new HttpsProxyAgent(options); + +// finally, initiate the WebSocket connection +var socket = new WebSocket(endpoint, { agent: agent }); + +socket.on('open', function () { + console.log('"open" event!'); + socket.send('hello world'); +}); + +socket.on('message', function (data, flags) { + console.log('"message" event! %j %j', data, flags); + socket.close(); +}); +``` + +API +--- + +### new HttpsProxyAgent(Object options) + +The `HttpsProxyAgent` class implements an `http.Agent` subclass that connects +to the specified "HTTP(s) proxy server" in order to proxy HTTPS and/or WebSocket +requests. This is achieved by using the [HTTP `CONNECT` method][CONNECT]. + +The `options` argument may either be a string URI of the proxy server to use, or an +"options" object with more specific properties: + + * `host` - String - Proxy host to connect to (may use `hostname` as well). Required. + * `port` - Number - Proxy port to connect to. Required. + * `protocol` - String - If `https:`, then use TLS to connect to the proxy. + * `headers` - Object - Additional HTTP headers to be sent on the HTTP CONNECT method. + * Any other options given are passed to the `net.connect()`/`tls.connect()` functions. + + +License +------- + +(The MIT License) + +Copyright (c) 2013 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. + +[CONNECT]: http://en.wikipedia.org/wiki/HTTP_tunnel#HTTP_CONNECT_Tunneling diff --git a/node_modules/https-proxy-agent/dist/agent.d.ts b/node_modules/https-proxy-agent/dist/agent.d.ts new file mode 100644 index 0000000..4f1c636 --- /dev/null +++ b/node_modules/https-proxy-agent/dist/agent.d.ts @@ -0,0 +1,30 @@ +/// +import net from 'net'; +import { Agent, ClientRequest, RequestOptions } from 'agent-base'; +import { HttpsProxyAgentOptions } from '.'; +/** + * The `HttpsProxyAgent` implements an HTTP Agent subclass that connects to + * the specified "HTTP(s) proxy server" in order to proxy HTTPS requests. + * + * Outgoing HTTP requests are first tunneled through the proxy server using the + * `CONNECT` HTTP request method to establish a connection to the proxy server, + * and then the proxy server connects to the destination target and issues the + * HTTP request from the proxy server. + * + * `https:` requests have their socket connection upgraded to TLS once + * the connection to the proxy server has been established. + * + * @api public + */ +export default class HttpsProxyAgent extends Agent { + private secureProxy; + private proxy; + constructor(_opts: string | HttpsProxyAgentOptions); + /** + * Called when the node-core HTTP client library is creating a + * new HTTP request. + * + * @api protected + */ + callback(req: ClientRequest, opts: RequestOptions): Promise; +} diff --git a/node_modules/https-proxy-agent/dist/agent.js b/node_modules/https-proxy-agent/dist/agent.js new file mode 100644 index 0000000..d666525 --- /dev/null +++ b/node_modules/https-proxy-agent/dist/agent.js @@ -0,0 +1,180 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const net_1 = __importDefault(require("net")); +const tls_1 = __importDefault(require("tls")); +const url_1 = __importDefault(require("url")); +const assert_1 = __importDefault(require("assert")); +const debug_1 = __importDefault(require("debug")); +const agent_base_1 = require("agent-base"); +const parse_proxy_response_1 = __importDefault(require("./parse-proxy-response")); +const debug = debug_1.default('https-proxy-agent:agent'); +/** + * The `HttpsProxyAgent` implements an HTTP Agent subclass that connects to + * the specified "HTTP(s) proxy server" in order to proxy HTTPS requests. + * + * Outgoing HTTP requests are first tunneled through the proxy server using the + * `CONNECT` HTTP request method to establish a connection to the proxy server, + * and then the proxy server connects to the destination target and issues the + * HTTP request from the proxy server. + * + * `https:` requests have their socket connection upgraded to TLS once + * the connection to the proxy server has been established. + * + * @api public + */ +class HttpsProxyAgent extends agent_base_1.Agent { + constructor(_opts) { + let opts; + if (typeof _opts === 'string') { + opts = url_1.default.parse(_opts); + } + else { + opts = _opts; + } + if (!opts) { + throw new Error('an HTTP(S) proxy server `host` and `port` must be specified!'); + } + debug('creating new HttpsProxyAgent instance: %o', opts); + super(opts); + const proxy = Object.assign({}, opts); + // If `true`, then connect to the proxy server over TLS. + // Defaults to `false`. + this.secureProxy = opts.secureProxy || isHTTPS(proxy.protocol); + // Prefer `hostname` over `host`, and set the `port` if needed. + proxy.host = proxy.hostname || proxy.host; + if (typeof proxy.port === 'string') { + proxy.port = parseInt(proxy.port, 10); + } + if (!proxy.port && proxy.host) { + proxy.port = this.secureProxy ? 443 : 80; + } + // ALPN is supported by Node.js >= v5. + // attempt to negotiate http/1.1 for proxy servers that support http/2 + if (this.secureProxy && !('ALPNProtocols' in proxy)) { + proxy.ALPNProtocols = ['http 1.1']; + } + if (proxy.host && proxy.path) { + // If both a `host` and `path` are specified then it's most likely + // the result of a `url.parse()` call... we need to remove the + // `path` portion so that `net.connect()` doesn't attempt to open + // that as a Unix socket file. + delete proxy.path; + delete proxy.pathname; + } + this.proxy = proxy; + } + /** + * Called when the node-core HTTP client library is creating a + * new HTTP request. + * + * @api protected + */ + callback(req, opts) { + return __awaiter(this, void 0, void 0, function* () { + const { proxy, secureProxy } = this; + // Create a socket connection to the proxy server. + let socket; + if (secureProxy) { + debug('Creating `tls.Socket`: %o', proxy); + socket = tls_1.default.connect(proxy); + } + else { + debug('Creating `net.Socket`: %o', proxy); + socket = net_1.default.connect(proxy); + } + const headers = Object.assign({}, proxy.headers); + const hostname = `${opts.host}:${opts.port}`; + let payload = `CONNECT ${hostname} HTTP/1.1\r\n`; + // Inject the `Proxy-Authorization` header if necessary. + if (proxy.auth) { + headers['Proxy-Authorization'] = `Basic ${Buffer.from(proxy.auth).toString('base64')}`; + } + // The `Host` header should only include the port + // number when it is not the default port. + let { host, port, secureEndpoint } = opts; + if (!isDefaultPort(port, secureEndpoint)) { + host += `:${port}`; + } + headers.Host = host; + headers.Connection = 'close'; + for (const name of Object.keys(headers)) { + payload += `${name}: ${headers[name]}\r\n`; + } + const proxyResponsePromise = parse_proxy_response_1.default(socket); + socket.write(`${payload}\r\n`); + const { statusCode, buffered } = yield proxyResponsePromise; + if (statusCode === 200) { + req.once('socket', resume); + if (opts.secureEndpoint) { + const servername = opts.servername || opts.host; + if (!servername) { + throw new Error('Could not determine "servername"'); + } + // The proxy is connecting to a TLS server, so upgrade + // this socket connection to a TLS connection. + debug('Upgrading socket connection to TLS'); + return tls_1.default.connect(Object.assign(Object.assign({}, omit(opts, 'host', 'hostname', 'path', 'port')), { socket, + servername })); + } + return socket; + } + // Some other status code that's not 200... need to re-play the HTTP + // header "data" events onto the socket once the HTTP machinery is + // attached so that the node core `http` can parse and handle the + // error status code. + // Close the original socket, and a new "fake" socket is returned + // instead, so that the proxy doesn't get the HTTP request + // written to it (which may contain `Authorization` headers or other + // sensitive data). + // + // See: https://hackerone.com/reports/541502 + socket.destroy(); + const fakeSocket = new net_1.default.Socket(); + fakeSocket.readable = true; + // Need to wait for the "socket" event to re-play the "data" events. + req.once('socket', (s) => { + debug('replaying proxy buffer for failed request'); + assert_1.default(s.listenerCount('data') > 0); + // Replay the "buffered" Buffer onto the fake `socket`, since at + // this point the HTTP module machinery has been hooked up for + // the user. + s.push(buffered); + s.push(null); + }); + return fakeSocket; + }); + } +} +exports.default = HttpsProxyAgent; +function resume(socket) { + socket.resume(); +} +function isDefaultPort(port, secure) { + return Boolean((!secure && port === 80) || (secure && port === 443)); +} +function isHTTPS(protocol) { + return typeof protocol === 'string' ? /^https:?$/i.test(protocol) : false; +} +function omit(obj, ...keys) { + const ret = {}; + let key; + for (key in obj) { + if (!keys.includes(key)) { + ret[key] = obj[key]; + } + } + return ret; +} +//# sourceMappingURL=agent.js.map \ No newline at end of file diff --git a/node_modules/https-proxy-agent/dist/agent.js.map b/node_modules/https-proxy-agent/dist/agent.js.map new file mode 100644 index 0000000..d1307cd --- /dev/null +++ b/node_modules/https-proxy-agent/dist/agent.js.map @@ -0,0 +1 @@ +{"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/node_modules/https-proxy-agent/dist/index.d.ts b/node_modules/https-proxy-agent/dist/index.d.ts new file mode 100644 index 0000000..0d60062 --- /dev/null +++ b/node_modules/https-proxy-agent/dist/index.d.ts @@ -0,0 +1,23 @@ +/// +import net from 'net'; +import tls from 'tls'; +import { Url } from 'url'; +import { AgentOptions } from 'agent-base'; +import { OutgoingHttpHeaders } from 'http'; +import _HttpsProxyAgent from './agent'; +declare function createHttpsProxyAgent(opts: string | createHttpsProxyAgent.HttpsProxyAgentOptions): _HttpsProxyAgent; +declare namespace createHttpsProxyAgent { + interface BaseHttpsProxyAgentOptions { + headers?: OutgoingHttpHeaders; + secureProxy?: boolean; + host?: string | null; + path?: string | null; + port?: string | number | null; + } + export interface HttpsProxyAgentOptions extends AgentOptions, BaseHttpsProxyAgentOptions, Partial> { + } + export type HttpsProxyAgent = _HttpsProxyAgent; + export const HttpsProxyAgent: typeof _HttpsProxyAgent; + export {}; +} +export = createHttpsProxyAgent; diff --git a/node_modules/https-proxy-agent/dist/index.js b/node_modules/https-proxy-agent/dist/index.js new file mode 100644 index 0000000..b03e763 --- /dev/null +++ b/node_modules/https-proxy-agent/dist/index.js @@ -0,0 +1,14 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +const agent_1 = __importDefault(require("./agent")); +function createHttpsProxyAgent(opts) { + return new agent_1.default(opts); +} +(function (createHttpsProxyAgent) { + createHttpsProxyAgent.HttpsProxyAgent = agent_1.default; + createHttpsProxyAgent.prototype = agent_1.default.prototype; +})(createHttpsProxyAgent || (createHttpsProxyAgent = {})); +module.exports = createHttpsProxyAgent; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/node_modules/https-proxy-agent/dist/index.js.map b/node_modules/https-proxy-agent/dist/index.js.map new file mode 100644 index 0000000..f3ce559 --- /dev/null +++ b/node_modules/https-proxy-agent/dist/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;AAKA,oDAAuC;AAEvC,SAAS,qBAAqB,CAC7B,IAA2D;IAE3D,OAAO,IAAI,eAAgB,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC;AAED,WAAU,qBAAqB;IAoBjB,qCAAe,GAAG,eAAgB,CAAC;IAEhD,qBAAqB,CAAC,SAAS,GAAG,eAAgB,CAAC,SAAS,CAAC;AAC9D,CAAC,EAvBS,qBAAqB,KAArB,qBAAqB,QAuB9B;AAED,iBAAS,qBAAqB,CAAC"} \ No newline at end of file diff --git a/node_modules/https-proxy-agent/dist/parse-proxy-response.d.ts b/node_modules/https-proxy-agent/dist/parse-proxy-response.d.ts new file mode 100644 index 0000000..7565674 --- /dev/null +++ b/node_modules/https-proxy-agent/dist/parse-proxy-response.d.ts @@ -0,0 +1,7 @@ +/// +import { Readable } from 'stream'; +export interface ProxyResponse { + statusCode: number; + buffered: Buffer; +} +export default function parseProxyResponse(socket: Readable): Promise; diff --git a/node_modules/https-proxy-agent/dist/parse-proxy-response.js b/node_modules/https-proxy-agent/dist/parse-proxy-response.js new file mode 100644 index 0000000..aa5ce3c --- /dev/null +++ b/node_modules/https-proxy-agent/dist/parse-proxy-response.js @@ -0,0 +1,66 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const debug_1 = __importDefault(require("debug")); +const debug = debug_1.default('https-proxy-agent:parse-proxy-response'); +function parseProxyResponse(socket) { + return new Promise((resolve, reject) => { + // we need to buffer any HTTP traffic that happens with the proxy before we get + // the CONNECT response, so that if the response is anything other than an "200" + // response code, then we can re-play the "data" events on the socket once the + // HTTP parser is hooked up... + let buffersLength = 0; + const buffers = []; + function read() { + const b = socket.read(); + if (b) + ondata(b); + else + socket.once('readable', read); + } + function cleanup() { + socket.removeListener('end', onend); + socket.removeListener('error', onerror); + socket.removeListener('close', onclose); + socket.removeListener('readable', read); + } + function onclose(err) { + debug('onclose had error %o', err); + } + function onend() { + debug('onend'); + } + function onerror(err) { + cleanup(); + debug('onerror %o', err); + reject(err); + } + function ondata(b) { + buffers.push(b); + buffersLength += b.length; + const buffered = Buffer.concat(buffers, buffersLength); + const endOfHeaders = buffered.indexOf('\r\n\r\n'); + if (endOfHeaders === -1) { + // keep buffering + debug('have not received end of HTTP headers yet...'); + read(); + return; + } + const firstLine = buffered.toString('ascii', 0, buffered.indexOf('\r\n')); + const statusCode = +firstLine.split(' ')[1]; + debug('got proxy server response: %o', firstLine); + resolve({ + statusCode, + buffered + }); + } + socket.on('error', onerror); + socket.on('close', onclose); + socket.on('end', onend); + read(); + }); +} +exports.default = parseProxyResponse; +//# sourceMappingURL=parse-proxy-response.js.map \ No newline at end of file diff --git a/node_modules/https-proxy-agent/dist/parse-proxy-response.js.map b/node_modules/https-proxy-agent/dist/parse-proxy-response.js.map new file mode 100644 index 0000000..bacdb84 --- /dev/null +++ b/node_modules/https-proxy-agent/dist/parse-proxy-response.js.map @@ -0,0 +1 @@ +{"version":3,"file":"parse-proxy-response.js","sourceRoot":"","sources":["../src/parse-proxy-response.ts"],"names":[],"mappings":";;;;;AAAA,kDAAgC;AAGhC,MAAM,KAAK,GAAG,eAAW,CAAC,wCAAwC,CAAC,CAAC;AAOpE,SAAwB,kBAAkB,CACzC,MAAgB;IAEhB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACtC,+EAA+E;QAC/E,gFAAgF;QAChF,8EAA8E;QAC9E,8BAA8B;QAC9B,IAAI,aAAa,GAAG,CAAC,CAAC;QACtB,MAAM,OAAO,GAAa,EAAE,CAAC;QAE7B,SAAS,IAAI;YACZ,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;YACxB,IAAI,CAAC;gBAAE,MAAM,CAAC,CAAC,CAAC,CAAC;;gBACZ,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACpC,CAAC;QAED,SAAS,OAAO;YACf,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YACpC,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACxC,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACxC,MAAM,CAAC,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACzC,CAAC;QAED,SAAS,OAAO,CAAC,GAAW;YAC3B,KAAK,CAAC,sBAAsB,EAAE,GAAG,CAAC,CAAC;QACpC,CAAC;QAED,SAAS,KAAK;YACb,KAAK,CAAC,OAAO,CAAC,CAAC;QAChB,CAAC;QAED,SAAS,OAAO,CAAC,GAAU;YAC1B,OAAO,EAAE,CAAC;YACV,KAAK,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;YACzB,MAAM,CAAC,GAAG,CAAC,CAAC;QACb,CAAC;QAED,SAAS,MAAM,CAAC,CAAS;YACxB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAChB,aAAa,IAAI,CAAC,CAAC,MAAM,CAAC;YAE1B,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;YACvD,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YAElD,IAAI,YAAY,KAAK,CAAC,CAAC,EAAE;gBACxB,iBAAiB;gBACjB,KAAK,CAAC,8CAA8C,CAAC,CAAC;gBACtD,IAAI,EAAE,CAAC;gBACP,OAAO;aACP;YAED,MAAM,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAClC,OAAO,EACP,CAAC,EACD,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CACxB,CAAC;YACF,MAAM,UAAU,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5C,KAAK,CAAC,+BAA+B,EAAE,SAAS,CAAC,CAAC;YAClD,OAAO,CAAC;gBACP,UAAU;gBACV,QAAQ;aACR,CAAC,CAAC;QACJ,CAAC;QAED,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC5B,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC5B,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAExB,IAAI,EAAE,CAAC;IACR,CAAC,CAAC,CAAC;AACJ,CAAC;AAvED,qCAuEC"} \ No newline at end of file diff --git a/node_modules/https-proxy-agent/package.json b/node_modules/https-proxy-agent/package.json new file mode 100644 index 0000000..0f47b75 --- /dev/null +++ b/node_modules/https-proxy-agent/package.json @@ -0,0 +1,86 @@ +{ + "_from": "https-proxy-agent@^5.0.0", + "_id": "https-proxy-agent@5.0.0", + "_inBundle": false, + "_integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "_location": "/https-proxy-agent", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "https-proxy-agent@^5.0.0", + "name": "https-proxy-agent", + "escapedName": "https-proxy-agent", + "rawSpec": "^5.0.0", + "saveSpec": null, + "fetchSpec": "^5.0.0" + }, + "_requiredBy": [ + "/web-push" + ], + "_resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "_shasum": "e2a90542abb68a762e0a0850f6c9edadfd8506b2", + "_spec": "https-proxy-agent@^5.0.0", + "_where": "D:\\Users\\user\\Documents\\Portofolio\\Github\\WebsiteFootballPWA\\node_modules\\web-push", + "author": { + "name": "Nathan Rajlich", + "email": "nathan@tootallnate.net", + "url": "http://n8.io/" + }, + "bugs": { + "url": "https://github.com/TooTallNate/node-https-proxy-agent/issues" + }, + "bundleDependencies": false, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "deprecated": false, + "description": "An HTTP(s) proxy `http.Agent` implementation for HTTPS", + "devDependencies": { + "@types/debug": "4", + "@types/node": "^12.12.11", + "@typescript-eslint/eslint-plugin": "1.6.0", + "@typescript-eslint/parser": "1.1.0", + "eslint": "5.16.0", + "eslint-config-airbnb": "17.1.0", + "eslint-config-prettier": "4.1.0", + "eslint-import-resolver-typescript": "1.1.1", + "eslint-plugin-import": "2.16.0", + "eslint-plugin-jsx-a11y": "6.2.1", + "eslint-plugin-react": "7.12.4", + "mocha": "^6.2.2", + "proxy": "1", + "rimraf": "^3.0.0", + "typescript": "^3.5.3" + }, + "engines": { + "node": ">= 6" + }, + "files": [ + "dist" + ], + "homepage": "https://github.com/TooTallNate/node-https-proxy-agent#readme", + "keywords": [ + "https", + "proxy", + "endpoint", + "agent" + ], + "license": "MIT", + "main": "dist/index", + "name": "https-proxy-agent", + "repository": { + "type": "git", + "url": "git://github.com/TooTallNate/node-https-proxy-agent.git" + }, + "scripts": { + "build": "tsc", + "prebuild": "rimraf dist", + "prepublishOnly": "npm run build", + "test": "mocha --reporter spec", + "test-lint": "eslint src --ext .js,.ts" + }, + "types": "dist/index", + "version": "5.0.0" +} diff --git a/node_modules/inherits/LICENSE b/node_modules/inherits/LICENSE new file mode 100644 index 0000000..dea3013 --- /dev/null +++ b/node_modules/inherits/LICENSE @@ -0,0 +1,16 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. + diff --git a/node_modules/inherits/README.md b/node_modules/inherits/README.md new file mode 100644 index 0000000..b1c5665 --- /dev/null +++ b/node_modules/inherits/README.md @@ -0,0 +1,42 @@ +Browser-friendly inheritance fully compatible with standard node.js +[inherits](http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor). + +This package exports standard `inherits` from node.js `util` module in +node environment, but also provides alternative browser-friendly +implementation through [browser +field](https://gist.github.com/shtylman/4339901). Alternative +implementation is a literal copy of standard one located in standalone +module to avoid requiring of `util`. It also has a shim for old +browsers with no `Object.create` support. + +While keeping you sure you are using standard `inherits` +implementation in node.js environment, it allows bundlers such as +[browserify](https://github.com/substack/node-browserify) to not +include full `util` package to your client code if all you need is +just `inherits` function. It worth, because browser shim for `util` +package is large and `inherits` is often the single function you need +from it. + +It's recommended to use this package instead of +`require('util').inherits` for any code that has chances to be used +not only in node.js but in browser too. + +## usage + +```js +var inherits = require('inherits'); +// then use exactly as the standard one +``` + +## note on version ~1.0 + +Version ~1.0 had completely different motivation and is not compatible +neither with 2.0 nor with standard node.js `inherits`. + +If you are using version ~1.0 and planning to switch to ~2.0, be +careful: + +* new version uses `super_` instead of `super` for referencing + superclass +* new version overwrites current prototype while old one preserves any + existing fields on it diff --git a/node_modules/inherits/inherits.js b/node_modules/inherits/inherits.js new file mode 100644 index 0000000..f71f2d9 --- /dev/null +++ b/node_modules/inherits/inherits.js @@ -0,0 +1,9 @@ +try { + var util = require('util'); + /* istanbul ignore next */ + if (typeof util.inherits !== 'function') throw ''; + module.exports = util.inherits; +} catch (e) { + /* istanbul ignore next */ + module.exports = require('./inherits_browser.js'); +} diff --git a/node_modules/inherits/inherits_browser.js b/node_modules/inherits/inherits_browser.js new file mode 100644 index 0000000..86bbb3d --- /dev/null +++ b/node_modules/inherits/inherits_browser.js @@ -0,0 +1,27 @@ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + if (superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }) + } + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + if (superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } + } +} diff --git a/node_modules/inherits/package.json b/node_modules/inherits/package.json new file mode 100644 index 0000000..8c49e11 --- /dev/null +++ b/node_modules/inherits/package.json @@ -0,0 +1,61 @@ +{ + "_from": "inherits@^2.0.1", + "_id": "inherits@2.0.4", + "_inBundle": false, + "_integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "_location": "/inherits", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "inherits@^2.0.1", + "name": "inherits", + "escapedName": "inherits", + "rawSpec": "^2.0.1", + "saveSpec": null, + "fetchSpec": "^2.0.1" + }, + "_requiredBy": [ + "/asn1.js" + ], + "_resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "_shasum": "0fa2c64f932917c3433a0ded55363aae37416b7c", + "_spec": "inherits@^2.0.1", + "_where": "D:\\Users\\user\\Documents\\Portofolio\\Github\\WebsiteFootballPWA\\node_modules\\asn1.js", + "browser": "./inherits_browser.js", + "bugs": { + "url": "https://github.com/isaacs/inherits/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Browser-friendly inheritance fully compatible with standard node.js inherits()", + "devDependencies": { + "tap": "^14.2.4" + }, + "files": [ + "inherits.js", + "inherits_browser.js" + ], + "homepage": "https://github.com/isaacs/inherits#readme", + "keywords": [ + "inheritance", + "class", + "klass", + "oop", + "object-oriented", + "inherits", + "browser", + "browserify" + ], + "license": "ISC", + "main": "./inherits.js", + "name": "inherits", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/inherits.git" + }, + "scripts": { + "test": "tap" + }, + "version": "2.0.4" +} diff --git a/node_modules/jwa/LICENSE b/node_modules/jwa/LICENSE new file mode 100644 index 0000000..caeb849 --- /dev/null +++ b/node_modules/jwa/LICENSE @@ -0,0 +1,17 @@ +Copyright (c) 2013 Brian J. Brennan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/jwa/README.md b/node_modules/jwa/README.md new file mode 100644 index 0000000..09e9648 --- /dev/null +++ b/node_modules/jwa/README.md @@ -0,0 +1,150 @@ +# node-jwa [![Build Status](https://travis-ci.org/brianloveswords/node-jwa.svg?branch=master)](https://travis-ci.org/brianloveswords/node-jwa) + +A +[JSON Web Algorithms](http://tools.ietf.org/id/draft-ietf-jose-json-web-algorithms-08.html) +implementation focusing (exclusively, at this point) on the algorithms necessary for +[JSON Web Signatures](http://self-issued.info/docs/draft-ietf-jose-json-web-signature.html). + +This library supports all of the required, recommended and optional cryptographic algorithms for JWS: + +alg Parameter Value | Digital Signature or MAC Algorithm +----------------|---------------------------- +HS256 | HMAC using SHA-256 hash algorithm +HS384 | HMAC using SHA-384 hash algorithm +HS512 | HMAC using SHA-512 hash algorithm +RS256 | RSASSA using SHA-256 hash algorithm +RS384 | RSASSA using SHA-384 hash algorithm +RS512 | RSASSA using SHA-512 hash algorithm +PS256 | RSASSA-PSS using SHA-256 hash algorithm +PS384 | RSASSA-PSS using SHA-384 hash algorithm +PS512 | RSASSA-PSS using SHA-512 hash algorithm +ES256 | ECDSA using P-256 curve and SHA-256 hash algorithm +ES384 | ECDSA using P-384 curve and SHA-384 hash algorithm +ES512 | ECDSA using P-521 curve and SHA-512 hash algorithm +none | No digital signature or MAC value included + +Please note that PS* only works on Node 6.12+ (excluding 7.x). + +# Requirements + +In order to run the tests, a recent version of OpenSSL is +required. **The version that comes with OS X (OpenSSL 0.9.8r 8 Feb +2011) is not recent enough**, as it does not fully support ECDSA +keys. You'll need to use a version > 1.0.0; I tested with OpenSSL 1.0.1c 10 May 2012. + +# Testing + +To run the tests, do + +```bash +$ npm test +``` + +This will generate a bunch of keypairs to use in testing. If you want to +generate new keypairs, do `make clean` before running `npm test` again. + +## Methodology + +I spawn `openssl dgst -sign` to test OpenSSL sign → JS verify and +`openssl dgst -verify` to test JS sign → OpenSSL verify for each of the +RSA and ECDSA algorithms. + +# Usage + +## jwa(algorithm) + +Creates a new `jwa` object with `sign` and `verify` methods for the +algorithm. Valid values for algorithm can be found in the table above +(`'HS256'`, `'HS384'`, etc) and are case-sensitive. Passing an invalid +algorithm value will throw a `TypeError`. + + +## jwa#sign(input, secretOrPrivateKey) + +Sign some input with either a secret for HMAC algorithms, or a private +key for RSA and ECDSA algorithms. + +If input is not already a string or buffer, `JSON.stringify` will be +called on it to attempt to coerce it. + +For the HMAC algorithm, `secretOrPrivateKey` should be a string or a +buffer. For ECDSA and RSA, the value should be a string representing a +PEM encoded **private** key. + +Output [base64url](http://en.wikipedia.org/wiki/Base64#URL_applications) +formatted. This is for convenience as JWS expects the signature in this +format. If your application needs the output in a different format, +[please open an issue](https://github.com/brianloveswords/node-jwa/issues). In +the meantime, you can use +[brianloveswords/base64url](https://github.com/brianloveswords/base64url) +to decode the signature. + +As of nodejs *v0.11.8*, SPKAC support was introduce. If your nodeJs +version satisfies, then you can pass an object `{ key: '..', passphrase: '...' }` + + +## jwa#verify(input, signature, secretOrPublicKey) + +Verify a signature. Returns `true` or `false`. + +`signature` should be a base64url encoded string. + +For the HMAC algorithm, `secretOrPublicKey` should be a string or a +buffer. For ECDSA and RSA, the value should be a string represented a +PEM encoded **public** key. + + +# Example + +HMAC +```js +const jwa = require('jwa'); + +const hmac = jwa('HS256'); +const input = 'super important stuff'; +const secret = 'shhhhhh'; + +const signature = hmac.sign(input, secret); +hmac.verify(input, signature, secret) // === true +hmac.verify(input, signature, 'trickery!') // === false +``` + +With keys +```js +const fs = require('fs'); +const jwa = require('jwa'); +const privateKey = fs.readFileSync(__dirname + '/ecdsa-p521-private.pem'); +const publicKey = fs.readFileSync(__dirname + '/ecdsa-p521-public.pem'); + +const ecdsa = jwa('ES512'); +const input = 'very important stuff'; + +const signature = ecdsa.sign(input, privateKey); +ecdsa.verify(input, signature, publicKey) // === true +``` +## License + +MIT + +``` +Copyright (c) 2013 Brian J. Brennan + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +``` diff --git a/node_modules/jwa/index.js b/node_modules/jwa/index.js new file mode 100644 index 0000000..d2061ef --- /dev/null +++ b/node_modules/jwa/index.js @@ -0,0 +1,252 @@ +var bufferEqual = require('buffer-equal-constant-time'); +var Buffer = require('safe-buffer').Buffer; +var crypto = require('crypto'); +var formatEcdsa = require('ecdsa-sig-formatter'); +var util = require('util'); + +var MSG_INVALID_ALGORITHM = '"%s" is not a valid algorithm.\n Supported algorithms are:\n "HS256", "HS384", "HS512", "RS256", "RS384", "RS512", "PS256", "PS384", "PS512", "ES256", "ES384", "ES512" and "none".' +var MSG_INVALID_SECRET = 'secret must be a string or buffer'; +var MSG_INVALID_VERIFIER_KEY = 'key must be a string or a buffer'; +var MSG_INVALID_SIGNER_KEY = 'key must be a string, a buffer or an object'; + +var supportsKeyObjects = typeof crypto.createPublicKey === 'function'; +if (supportsKeyObjects) { + MSG_INVALID_VERIFIER_KEY += ' or a KeyObject'; + MSG_INVALID_SECRET += 'or a KeyObject'; +} + +function checkIsPublicKey(key) { + if (Buffer.isBuffer(key)) { + return; + } + + if (typeof key === 'string') { + return; + } + + if (!supportsKeyObjects) { + throw typeError(MSG_INVALID_VERIFIER_KEY); + } + + if (typeof key !== 'object') { + throw typeError(MSG_INVALID_VERIFIER_KEY); + } + + if (typeof key.type !== 'string') { + throw typeError(MSG_INVALID_VERIFIER_KEY); + } + + if (typeof key.asymmetricKeyType !== 'string') { + throw typeError(MSG_INVALID_VERIFIER_KEY); + } + + if (typeof key.export !== 'function') { + throw typeError(MSG_INVALID_VERIFIER_KEY); + } +}; + +function checkIsPrivateKey(key) { + if (Buffer.isBuffer(key)) { + return; + } + + if (typeof key === 'string') { + return; + } + + if (typeof key === 'object') { + return; + } + + throw typeError(MSG_INVALID_SIGNER_KEY); +}; + +function checkIsSecretKey(key) { + if (Buffer.isBuffer(key)) { + return; + } + + if (typeof key === 'string') { + return key; + } + + if (!supportsKeyObjects) { + throw typeError(MSG_INVALID_SECRET); + } + + if (typeof key !== 'object') { + throw typeError(MSG_INVALID_SECRET); + } + + if (key.type !== 'secret') { + throw typeError(MSG_INVALID_SECRET); + } + + if (typeof key.export !== 'function') { + throw typeError(MSG_INVALID_SECRET); + } +} + +function fromBase64(base64) { + return base64 + .replace(/=/g, '') + .replace(/\+/g, '-') + .replace(/\//g, '_'); +} + +function toBase64(base64url) { + base64url = base64url.toString(); + + var padding = 4 - base64url.length % 4; + if (padding !== 4) { + for (var i = 0; i < padding; ++i) { + base64url += '='; + } + } + + return base64url + .replace(/\-/g, '+') + .replace(/_/g, '/'); +} + +function typeError(template) { + var args = [].slice.call(arguments, 1); + var errMsg = util.format.bind(util, template).apply(null, args); + return new TypeError(errMsg); +} + +function bufferOrString(obj) { + return Buffer.isBuffer(obj) || typeof obj === 'string'; +} + +function normalizeInput(thing) { + if (!bufferOrString(thing)) + thing = JSON.stringify(thing); + return thing; +} + +function createHmacSigner(bits) { + return function sign(thing, secret) { + checkIsSecretKey(secret); + thing = normalizeInput(thing); + var hmac = crypto.createHmac('sha' + bits, secret); + var sig = (hmac.update(thing), hmac.digest('base64')) + return fromBase64(sig); + } +} + +function createHmacVerifier(bits) { + return function verify(thing, signature, secret) { + var computedSig = createHmacSigner(bits)(thing, secret); + return bufferEqual(Buffer.from(signature), Buffer.from(computedSig)); + } +} + +function createKeySigner(bits) { + return function sign(thing, privateKey) { + checkIsPrivateKey(privateKey); + thing = normalizeInput(thing); + // Even though we are specifying "RSA" here, this works with ECDSA + // keys as well. + var signer = crypto.createSign('RSA-SHA' + bits); + var sig = (signer.update(thing), signer.sign(privateKey, 'base64')); + return fromBase64(sig); + } +} + +function createKeyVerifier(bits) { + return function verify(thing, signature, publicKey) { + checkIsPublicKey(publicKey); + thing = normalizeInput(thing); + signature = toBase64(signature); + var verifier = crypto.createVerify('RSA-SHA' + bits); + verifier.update(thing); + return verifier.verify(publicKey, signature, 'base64'); + } +} + +function createPSSKeySigner(bits) { + return function sign(thing, privateKey) { + checkIsPrivateKey(privateKey); + thing = normalizeInput(thing); + var signer = crypto.createSign('RSA-SHA' + bits); + var sig = (signer.update(thing), signer.sign({ + key: privateKey, + padding: crypto.constants.RSA_PKCS1_PSS_PADDING, + saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST + }, 'base64')); + return fromBase64(sig); + } +} + +function createPSSKeyVerifier(bits) { + return function verify(thing, signature, publicKey) { + checkIsPublicKey(publicKey); + thing = normalizeInput(thing); + signature = toBase64(signature); + var verifier = crypto.createVerify('RSA-SHA' + bits); + verifier.update(thing); + return verifier.verify({ + key: publicKey, + padding: crypto.constants.RSA_PKCS1_PSS_PADDING, + saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST + }, signature, 'base64'); + } +} + +function createECDSASigner(bits) { + var inner = createKeySigner(bits); + return function sign() { + var signature = inner.apply(null, arguments); + signature = formatEcdsa.derToJose(signature, 'ES' + bits); + return signature; + }; +} + +function createECDSAVerifer(bits) { + var inner = createKeyVerifier(bits); + return function verify(thing, signature, publicKey) { + signature = formatEcdsa.joseToDer(signature, 'ES' + bits).toString('base64'); + var result = inner(thing, signature, publicKey); + return result; + }; +} + +function createNoneSigner() { + return function sign() { + return ''; + } +} + +function createNoneVerifier() { + return function verify(thing, signature) { + return signature === ''; + } +} + +module.exports = function jwa(algorithm) { + var signerFactories = { + hs: createHmacSigner, + rs: createKeySigner, + ps: createPSSKeySigner, + es: createECDSASigner, + none: createNoneSigner, + } + var verifierFactories = { + hs: createHmacVerifier, + rs: createKeyVerifier, + ps: createPSSKeyVerifier, + es: createECDSAVerifer, + none: createNoneVerifier, + } + var match = algorithm.match(/^(RS|PS|ES|HS)(256|384|512)$|^(none)$/); + if (!match) + throw typeError(MSG_INVALID_ALGORITHM, algorithm); + var algo = (match[1] || match[3]).toLowerCase(); + var bits = match[2]; + + return { + sign: signerFactories[algo](bits), + verify: verifierFactories[algo](bits), + } +}; diff --git a/node_modules/jwa/package.json b/node_modules/jwa/package.json new file mode 100644 index 0000000..d7574fb --- /dev/null +++ b/node_modules/jwa/package.json @@ -0,0 +1,69 @@ +{ + "_from": "jwa@^2.0.0", + "_id": "jwa@2.0.0", + "_inBundle": false, + "_integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "_location": "/jwa", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "jwa@^2.0.0", + "name": "jwa", + "escapedName": "jwa", + "rawSpec": "^2.0.0", + "saveSpec": null, + "fetchSpec": "^2.0.0" + }, + "_requiredBy": [ + "/jws" + ], + "_resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "_shasum": "a7e9c3f29dae94027ebcaf49975c9345593410fc", + "_spec": "jwa@^2.0.0", + "_where": "D:\\Users\\user\\Documents\\Portofolio\\Github\\WebsiteFootballPWA\\node_modules\\jws", + "author": { + "name": "Brian J. Brennan", + "email": "brianloveswords@gmail.com" + }, + "bugs": { + "url": "https://github.com/brianloveswords/node-jwa/issues" + }, + "bundleDependencies": false, + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + }, + "deprecated": false, + "description": "JWA implementation (supports all JWS algorithms)", + "devDependencies": { + "base64url": "^2.0.0", + "jwk-to-pem": "^2.0.1", + "semver": "4.3.6", + "tap": "6.2.0" + }, + "directories": { + "test": "test" + }, + "homepage": "https://github.com/brianloveswords/node-jwa#readme", + "keywords": [ + "jwa", + "jws", + "jwt", + "rsa", + "ecdsa", + "hmac" + ], + "license": "MIT", + "main": "index.js", + "name": "jwa", + "repository": { + "type": "git", + "url": "git://github.com/brianloveswords/node-jwa.git" + }, + "scripts": { + "test": "make test" + }, + "version": "2.0.0" +} diff --git a/node_modules/jws/CHANGELOG.md b/node_modules/jws/CHANGELOG.md new file mode 100644 index 0000000..af8fc28 --- /dev/null +++ b/node_modules/jws/CHANGELOG.md @@ -0,0 +1,34 @@ +# Change Log +All notable changes to this project will be documented in this file. + +## [3.0.0] +### Changed +- **BREAKING**: `jwt.verify` now requires an `algorithm` parameter, and + `jws.createVerify` requires an `algorithm` option. The `"alg"` field + signature headers is ignored. This mitigates a critical security flaw + in the library which would allow an attacker to generate signatures with + arbitrary contents that would be accepted by `jwt.verify`. See + https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/ + for details. + +## [2.0.0] - 2015-01-30 +### Changed +- **BREAKING**: Default payload encoding changed from `binary` to + `utf8`. `utf8` is a is a more sensible default than `binary` because + many payloads, as far as I can tell, will contain user-facing + strings that could be in any language. ([6b6de48]) + +- Code reorganization, thanks [@fearphage]! ([7880050]) + +### Added +- Option in all relevant methods for `encoding`. For those few users + that might be depending on a `binary` encoding of the messages, this + is for them. ([6b6de48]) + +[unreleased]: https://github.com/brianloveswords/node-jws/compare/v2.0.0...HEAD +[2.0.0]: https://github.com/brianloveswords/node-jws/compare/v1.0.1...v2.0.0 + +[7880050]: https://github.com/brianloveswords/node-jws/commit/7880050 +[6b6de48]: https://github.com/brianloveswords/node-jws/commit/6b6de48 + +[@fearphage]: https://github.com/fearphage diff --git a/node_modules/jws/LICENSE b/node_modules/jws/LICENSE new file mode 100644 index 0000000..caeb849 --- /dev/null +++ b/node_modules/jws/LICENSE @@ -0,0 +1,17 @@ +Copyright (c) 2013 Brian J. Brennan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/jws/index.js b/node_modules/jws/index.js new file mode 100644 index 0000000..8c8da93 --- /dev/null +++ b/node_modules/jws/index.js @@ -0,0 +1,22 @@ +/*global exports*/ +var SignStream = require('./lib/sign-stream'); +var VerifyStream = require('./lib/verify-stream'); + +var ALGORITHMS = [ + 'HS256', 'HS384', 'HS512', + 'RS256', 'RS384', 'RS512', + 'PS256', 'PS384', 'PS512', + 'ES256', 'ES384', 'ES512' +]; + +exports.ALGORITHMS = ALGORITHMS; +exports.sign = SignStream.sign; +exports.verify = VerifyStream.verify; +exports.decode = VerifyStream.decode; +exports.isValid = VerifyStream.isValid; +exports.createSign = function createSign(opts) { + return new SignStream(opts); +}; +exports.createVerify = function createVerify(opts) { + return new VerifyStream(opts); +}; diff --git a/node_modules/jws/lib/data-stream.js b/node_modules/jws/lib/data-stream.js new file mode 100644 index 0000000..3535d31 --- /dev/null +++ b/node_modules/jws/lib/data-stream.js @@ -0,0 +1,55 @@ +/*global module, process*/ +var Buffer = require('safe-buffer').Buffer; +var Stream = require('stream'); +var util = require('util'); + +function DataStream(data) { + this.buffer = null; + this.writable = true; + this.readable = true; + + // No input + if (!data) { + this.buffer = Buffer.alloc(0); + return this; + } + + // Stream + if (typeof data.pipe === 'function') { + this.buffer = Buffer.alloc(0); + data.pipe(this); + return this; + } + + // Buffer or String + // or Object (assumedly a passworded key) + if (data.length || typeof data === 'object') { + this.buffer = data; + this.writable = false; + process.nextTick(function () { + this.emit('end', data); + this.readable = false; + this.emit('close'); + }.bind(this)); + return this; + } + + throw new TypeError('Unexpected data type ('+ typeof data + ')'); +} +util.inherits(DataStream, Stream); + +DataStream.prototype.write = function write(data) { + this.buffer = Buffer.concat([this.buffer, Buffer.from(data)]); + this.emit('data', data); +}; + +DataStream.prototype.end = function end(data) { + if (data) + this.write(data); + this.emit('end', data); + this.emit('close'); + this.writable = false; + this.readable = false; +}; + +module.exports = DataStream; diff --git a/node_modules/jws/lib/sign-stream.js b/node_modules/jws/lib/sign-stream.js new file mode 100644 index 0000000..6a7ee42 --- /dev/null +++ b/node_modules/jws/lib/sign-stream.js @@ -0,0 +1,78 @@ +/*global module*/ +var Buffer = require('safe-buffer').Buffer; +var DataStream = require('./data-stream'); +var jwa = require('jwa'); +var Stream = require('stream'); +var toString = require('./tostring'); +var util = require('util'); + +function base64url(string, encoding) { + return Buffer + .from(string, encoding) + .toString('base64') + .replace(/=/g, '') + .replace(/\+/g, '-') + .replace(/\//g, '_'); +} + +function jwsSecuredInput(header, payload, encoding) { + encoding = encoding || 'utf8'; + var encodedHeader = base64url(toString(header), 'binary'); + var encodedPayload = base64url(toString(payload), encoding); + return util.format('%s.%s', encodedHeader, encodedPayload); +} + +function jwsSign(opts) { + var header = opts.header; + var payload = opts.payload; + var secretOrKey = opts.secret || opts.privateKey; + var encoding = opts.encoding; + var algo = jwa(header.alg); + var securedInput = jwsSecuredInput(header, payload, encoding); + var signature = algo.sign(securedInput, secretOrKey); + return util.format('%s.%s', securedInput, signature); +} + +function SignStream(opts) { + var secret = opts.secret||opts.privateKey||opts.key; + var secretStream = new DataStream(secret); + this.readable = true; + this.header = opts.header; + this.encoding = opts.encoding; + this.secret = this.privateKey = this.key = secretStream; + this.payload = new DataStream(opts.payload); + this.secret.once('close', function () { + if (!this.payload.writable && this.readable) + this.sign(); + }.bind(this)); + + this.payload.once('close', function () { + if (!this.secret.writable && this.readable) + this.sign(); + }.bind(this)); +} +util.inherits(SignStream, Stream); + +SignStream.prototype.sign = function sign() { + try { + var signature = jwsSign({ + header: this.header, + payload: this.payload.buffer, + secret: this.secret.buffer, + encoding: this.encoding + }); + this.emit('done', signature); + this.emit('data', signature); + this.emit('end'); + this.readable = false; + return signature; + } catch (e) { + this.readable = false; + this.emit('error', e); + this.emit('close'); + } +}; + +SignStream.sign = jwsSign; + +module.exports = SignStream; diff --git a/node_modules/jws/lib/tostring.js b/node_modules/jws/lib/tostring.js new file mode 100644 index 0000000..f5a49a3 --- /dev/null +++ b/node_modules/jws/lib/tostring.js @@ -0,0 +1,10 @@ +/*global module*/ +var Buffer = require('buffer').Buffer; + +module.exports = function toString(obj) { + if (typeof obj === 'string') + return obj; + if (typeof obj === 'number' || Buffer.isBuffer(obj)) + return obj.toString(); + return JSON.stringify(obj); +}; diff --git a/node_modules/jws/lib/verify-stream.js b/node_modules/jws/lib/verify-stream.js new file mode 100644 index 0000000..39f7c73 --- /dev/null +++ b/node_modules/jws/lib/verify-stream.js @@ -0,0 +1,120 @@ +/*global module*/ +var Buffer = require('safe-buffer').Buffer; +var DataStream = require('./data-stream'); +var jwa = require('jwa'); +var Stream = require('stream'); +var toString = require('./tostring'); +var util = require('util'); +var JWS_REGEX = /^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/; + +function isObject(thing) { + return Object.prototype.toString.call(thing) === '[object Object]'; +} + +function safeJsonParse(thing) { + if (isObject(thing)) + return thing; + try { return JSON.parse(thing); } + catch (e) { return undefined; } +} + +function headerFromJWS(jwsSig) { + var encodedHeader = jwsSig.split('.', 1)[0]; + return safeJsonParse(Buffer.from(encodedHeader, 'base64').toString('binary')); +} + +function securedInputFromJWS(jwsSig) { + return jwsSig.split('.', 2).join('.'); +} + +function signatureFromJWS(jwsSig) { + return jwsSig.split('.')[2]; +} + +function payloadFromJWS(jwsSig, encoding) { + encoding = encoding || 'utf8'; + var payload = jwsSig.split('.')[1]; + return Buffer.from(payload, 'base64').toString(encoding); +} + +function isValidJws(string) { + return JWS_REGEX.test(string) && !!headerFromJWS(string); +} + +function jwsVerify(jwsSig, algorithm, secretOrKey) { + if (!algorithm) { + var err = new Error("Missing algorithm parameter for jws.verify"); + err.code = "MISSING_ALGORITHM"; + throw err; + } + jwsSig = toString(jwsSig); + var signature = signatureFromJWS(jwsSig); + var securedInput = securedInputFromJWS(jwsSig); + var algo = jwa(algorithm); + return algo.verify(securedInput, signature, secretOrKey); +} + +function jwsDecode(jwsSig, opts) { + opts = opts || {}; + jwsSig = toString(jwsSig); + + if (!isValidJws(jwsSig)) + return null; + + var header = headerFromJWS(jwsSig); + + if (!header) + return null; + + var payload = payloadFromJWS(jwsSig); + if (header.typ === 'JWT' || opts.json) + payload = JSON.parse(payload, opts.encoding); + + return { + header: header, + payload: payload, + signature: signatureFromJWS(jwsSig) + }; +} + +function VerifyStream(opts) { + opts = opts || {}; + var secretOrKey = opts.secret||opts.publicKey||opts.key; + var secretStream = new DataStream(secretOrKey); + this.readable = true; + this.algorithm = opts.algorithm; + this.encoding = opts.encoding; + this.secret = this.publicKey = this.key = secretStream; + this.signature = new DataStream(opts.signature); + this.secret.once('close', function () { + if (!this.signature.writable && this.readable) + this.verify(); + }.bind(this)); + + this.signature.once('close', function () { + if (!this.secret.writable && this.readable) + this.verify(); + }.bind(this)); +} +util.inherits(VerifyStream, Stream); +VerifyStream.prototype.verify = function verify() { + try { + var valid = jwsVerify(this.signature.buffer, this.algorithm, this.key.buffer); + var obj = jwsDecode(this.signature.buffer, this.encoding); + this.emit('done', valid, obj); + this.emit('data', valid); + this.emit('end'); + this.readable = false; + return valid; + } catch (e) { + this.readable = false; + this.emit('error', e); + this.emit('close'); + } +}; + +VerifyStream.decode = jwsDecode; +VerifyStream.isValid = isValidJws; +VerifyStream.verify = jwsVerify; + +module.exports = VerifyStream; diff --git a/node_modules/jws/package.json b/node_modules/jws/package.json new file mode 100644 index 0000000..9d7f979 --- /dev/null +++ b/node_modules/jws/package.json @@ -0,0 +1,64 @@ +{ + "_from": "jws@^4.0.0", + "_id": "jws@4.0.0", + "_inBundle": false, + "_integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "_location": "/jws", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "jws@^4.0.0", + "name": "jws", + "escapedName": "jws", + "rawSpec": "^4.0.0", + "saveSpec": null, + "fetchSpec": "^4.0.0" + }, + "_requiredBy": [ + "/web-push" + ], + "_resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "_shasum": "2d4e8cf6a318ffaa12615e9dec7e86e6c97310f4", + "_spec": "jws@^4.0.0", + "_where": "D:\\Users\\user\\Documents\\Portofolio\\Github\\WebsiteFootballPWA\\node_modules\\web-push", + "author": { + "name": "Brian J Brennan" + }, + "bugs": { + "url": "https://github.com/brianloveswords/node-jws/issues" + }, + "bundleDependencies": false, + "dependencies": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + }, + "deprecated": false, + "description": "Implementation of JSON Web Signatures", + "devDependencies": { + "semver": "^5.1.0", + "tape": "~2.14.0" + }, + "directories": { + "test": "test" + }, + "gitHead": "c0f6b27bcea5a2ad2e304d91c2e842e4076a6b03", + "homepage": "https://github.com/brianloveswords/node-jws#readme", + "keywords": [ + "jws", + "json", + "web", + "signatures" + ], + "license": "MIT", + "main": "index.js", + "name": "jws", + "repository": { + "type": "git", + "url": "git://github.com/brianloveswords/node-jws.git" + }, + "scripts": { + "test": "make test" + }, + "version": "4.0.0" +} diff --git a/node_modules/jws/readme.md b/node_modules/jws/readme.md new file mode 100644 index 0000000..2f32dca --- /dev/null +++ b/node_modules/jws/readme.md @@ -0,0 +1,255 @@ +# node-jws [![Build Status](https://secure.travis-ci.org/brianloveswords/node-jws.svg)](http://travis-ci.org/brianloveswords/node-jws) + +An implementation of [JSON Web Signatures](http://self-issued.info/docs/draft-ietf-jose-json-web-signature.html). + +This was developed against `draft-ietf-jose-json-web-signature-08` and +implements the entire spec **except** X.509 Certificate Chain +signing/verifying (patches welcome). + +There are both synchronous (`jws.sign`, `jws.verify`) and streaming +(`jws.createSign`, `jws.createVerify`) APIs. + +# Install + +```bash +$ npm install jws +``` + +# Usage + +## jws.ALGORITHMS + +Array of supported algorithms. The following algorithms are currently supported. + +alg Parameter Value | Digital Signature or MAC Algorithm +----------------|---------------------------- +HS256 | HMAC using SHA-256 hash algorithm +HS384 | HMAC using SHA-384 hash algorithm +HS512 | HMAC using SHA-512 hash algorithm +RS256 | RSASSA using SHA-256 hash algorithm +RS384 | RSASSA using SHA-384 hash algorithm +RS512 | RSASSA using SHA-512 hash algorithm +PS256 | RSASSA-PSS using SHA-256 hash algorithm +PS384 | RSASSA-PSS using SHA-384 hash algorithm +PS512 | RSASSA-PSS using SHA-512 hash algorithm +ES256 | ECDSA using P-256 curve and SHA-256 hash algorithm +ES384 | ECDSA using P-384 curve and SHA-384 hash algorithm +ES512 | ECDSA using P-521 curve and SHA-512 hash algorithm +none | No digital signature or MAC value included + +## jws.sign(options) + +(Synchronous) Return a JSON Web Signature for a header and a payload. + +Options: + +* `header` +* `payload` +* `secret` or `privateKey` +* `encoding` (Optional, defaults to 'utf8') + +`header` must be an object with an `alg` property. `header.alg` must be +one a value found in `jws.ALGORITHMS`. See above for a table of +supported algorithms. + +If `payload` is not a buffer or a string, it will be coerced into a string +using `JSON.stringify`. + +Example + +```js +const signature = jws.sign({ + header: { alg: 'HS256' }, + payload: 'h. jon benjamin', + secret: 'has a van', +}); +``` + +## jws.verify(signature, algorithm, secretOrKey) + +(Synchronous) Returns `true` or `false` for whether a signature matches a +secret or key. + +`signature` is a JWS Signature. `header.alg` must be a value found in `jws.ALGORITHMS`. +See above for a table of supported algorithms. `secretOrKey` is a string or +buffer containing either the secret for HMAC algorithms, or the PEM +encoded public key for RSA and ECDSA. + +Note that the `"alg"` value from the signature header is ignored. + + +## jws.decode(signature) + +(Synchronous) Returns the decoded header, decoded payload, and signature +parts of the JWS Signature. + +Returns an object with three properties, e.g. +```js +{ header: { alg: 'HS256' }, + payload: 'h. jon benjamin', + signature: 'YOWPewyGHKu4Y_0M_vtlEnNlqmFOclqp4Hy6hVHfFT4' +} +``` + +## jws.createSign(options) + +Returns a new SignStream object. + +Options: + +* `header` (required) +* `payload` +* `key` || `privateKey` || `secret` +* `encoding` (Optional, defaults to 'utf8') + +Other than `header`, all options expect a string or a buffer when the +value is known ahead of time, or a stream for convenience. +`key`/`privateKey`/`secret` may also be an object when using an encrypted +private key, see the [crypto documentation][encrypted-key-docs]. + +Example: + +```js + +// This... +jws.createSign({ + header: { alg: 'RS256' }, + privateKey: privateKeyStream, + payload: payloadStream, +}).on('done', function(signature) { + // ... +}); + +// is equivalent to this: +const signer = jws.createSign({ + header: { alg: 'RS256' }, +}); +privateKeyStream.pipe(signer.privateKey); +payloadStream.pipe(signer.payload); +signer.on('done', function(signature) { + // ... +}); +``` + +## jws.createVerify(options) + +Returns a new VerifyStream object. + +Options: + +* `signature` +* `algorithm` +* `key` || `publicKey` || `secret` +* `encoding` (Optional, defaults to 'utf8') + +All options expect a string or a buffer when the value is known ahead of +time, or a stream for convenience. + +Example: + +```js + +// This... +jws.createVerify({ + publicKey: pubKeyStream, + signature: sigStream, +}).on('done', function(verified, obj) { + // ... +}); + +// is equivilant to this: +const verifier = jws.createVerify(); +pubKeyStream.pipe(verifier.publicKey); +sigStream.pipe(verifier.signature); +verifier.on('done', function(verified, obj) { + // ... +}); +``` + +## Class: SignStream + +A `Readable Stream` that emits a single data event (the calculated +signature) when done. + +### Event: 'done' +`function (signature) { }` + +### signer.payload + +A `Writable Stream` that expects the JWS payload. Do *not* use if you +passed a `payload` option to the constructor. + +Example: + +```js +payloadStream.pipe(signer.payload); +``` + +### signer.secret
    signer.key
    signer.privateKey + +A `Writable Stream`. Expects the JWS secret for HMAC, or the privateKey +for ECDSA and RSA. Do *not* use if you passed a `secret` or `key` option +to the constructor. + +Example: + +```js +privateKeyStream.pipe(signer.privateKey); +``` + +## Class: VerifyStream + +This is a `Readable Stream` that emits a single data event, the result +of whether or not that signature was valid. + +### Event: 'done' +`function (valid, obj) { }` + +`valid` is a boolean for whether or not the signature is valid. + +### verifier.signature + +A `Writable Stream` that expects a JWS Signature. Do *not* use if you +passed a `signature` option to the constructor. + +### verifier.secret
    verifier.key
    verifier.publicKey + +A `Writable Stream` that expects a public key or secret. Do *not* use if you +passed a `key` or `secret` option to the constructor. + +# TODO + +* It feels like there should be some convenience options/APIs for + defining the algorithm rather than having to define a header object + with `{ alg: 'ES512' }` or whatever every time. + +* X.509 support, ugh + +# License + +MIT + +``` +Copyright (c) 2013-2015 Brian J. Brennan + +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. +``` + +[encrypted-key-docs]: https://nodejs.org/api/crypto.html#crypto_sign_sign_private_key_output_format diff --git a/node_modules/minimalistic-assert/LICENSE b/node_modules/minimalistic-assert/LICENSE new file mode 100644 index 0000000..adca66b --- /dev/null +++ b/node_modules/minimalistic-assert/LICENSE @@ -0,0 +1,13 @@ +Copyright 2015 Calvin Metcalf + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright notice +and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file diff --git a/node_modules/minimalistic-assert/index.js b/node_modules/minimalistic-assert/index.js new file mode 100644 index 0000000..70b4ea5 --- /dev/null +++ b/node_modules/minimalistic-assert/index.js @@ -0,0 +1,11 @@ +module.exports = assert; + +function assert(val, msg) { + if (!val) + throw new Error(msg || 'Assertion failed'); +} + +assert.equal = function assertEqual(l, r, msg) { + if (l != r) + throw new Error(msg || ('Assertion failed: ' + l + ' != ' + r)); +}; diff --git a/node_modules/minimalistic-assert/package.json b/node_modules/minimalistic-assert/package.json new file mode 100644 index 0000000..ed53011 --- /dev/null +++ b/node_modules/minimalistic-assert/package.json @@ -0,0 +1,44 @@ +{ + "_from": "minimalistic-assert@^1.0.0", + "_id": "minimalistic-assert@1.0.1", + "_inBundle": false, + "_integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "_location": "/minimalistic-assert", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "minimalistic-assert@^1.0.0", + "name": "minimalistic-assert", + "escapedName": "minimalistic-assert", + "rawSpec": "^1.0.0", + "saveSpec": null, + "fetchSpec": "^1.0.0" + }, + "_requiredBy": [ + "/asn1.js" + ], + "_resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "_shasum": "2e194de044626d4a10e7f7fbc00ce73e83e4d5c7", + "_spec": "minimalistic-assert@^1.0.0", + "_where": "D:\\Users\\user\\Documents\\Portofolio\\Github\\WebsiteFootballPWA\\node_modules\\asn1.js", + "author": "", + "bugs": { + "url": "https://github.com/calvinmetcalf/minimalistic-assert/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "minimalistic-assert ===", + "homepage": "https://github.com/calvinmetcalf/minimalistic-assert", + "license": "ISC", + "main": "index.js", + "name": "minimalistic-assert", + "repository": { + "type": "git", + "url": "git+https://github.com/calvinmetcalf/minimalistic-assert.git" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "version": "1.0.1" +} diff --git a/node_modules/minimalistic-assert/readme.md b/node_modules/minimalistic-assert/readme.md new file mode 100644 index 0000000..2ca0d25 --- /dev/null +++ b/node_modules/minimalistic-assert/readme.md @@ -0,0 +1,4 @@ +minimalistic-assert +=== + +very minimalistic assert module. diff --git a/node_modules/minimist/.travis.yml b/node_modules/minimist/.travis.yml new file mode 100644 index 0000000..74c57bf --- /dev/null +++ b/node_modules/minimist/.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/node_modules/minimist/LICENSE b/node_modules/minimist/LICENSE new file mode 100644 index 0000000..ee27ba4 --- /dev/null +++ b/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/node_modules/minimist/example/parse.js b/node_modules/minimist/example/parse.js new file mode 100644 index 0000000..f7c8d49 --- /dev/null +++ b/node_modules/minimist/example/parse.js @@ -0,0 +1,2 @@ +var argv = require('../')(process.argv.slice(2)); +console.log(argv); diff --git a/node_modules/minimist/index.js b/node_modules/minimist/index.js new file mode 100644 index 0000000..d2afe5e --- /dev/null +++ b/node_modules/minimist/index.js @@ -0,0 +1,245 @@ +module.exports = function (args, opts) { + if (!opts) opts = {}; + + var flags = { bools : {}, strings : {}, unknownFn: null }; + + if (typeof opts['unknown'] === 'function') { + flags.unknownFn = opts['unknown']; + } + + if (typeof opts['boolean'] === 'boolean' && opts['boolean']) { + flags.allBools = true; + } else { + [].concat(opts['boolean']).filter(Boolean).forEach(function (key) { + flags.bools[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; + })); + }); + }); + + [].concat(opts.string).filter(Boolean).forEach(function (key) { + flags.strings[key] = true; + if (aliases[key]) { + flags.strings[aliases[key]] = true; + } + }); + + 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 argDefined(key, arg) { + return (flags.allBools && /^--[^=]+$/.test(arg)) || + flags.strings[key] || flags.bools[key] || aliases[key]; + } + + function setArg (key, val, arg) { + if (arg && flags.unknownFn && !argDefined(key, arg)) { + if (flags.unknownFn(arg) === false) return; + } + + 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); + }); + } + + function setKey (obj, keys, value) { + var o = obj; + for (var i = 0; i < keys.length-1; i++) { + var key = keys[i]; + if (key === '__proto__') return; + if (o[key] === undefined) o[key] = {}; + if (o[key] === Object.prototype || o[key] === Number.prototype + || o[key] === String.prototype) o[key] = {}; + if (o[key] === Array.prototype) o[key] = []; + o = o[key]; + } + + var key = keys[keys.length - 1]; + if (key === '__proto__') return; + if (o === Object.prototype || o === Number.prototype + || o === String.prototype) o = {}; + if (o === Array.prototype) o = []; + if (o[key] === undefined || flags.bools[key] || typeof o[key] === 'boolean') { + o[key] = value; + } + else if (Array.isArray(o[key])) { + o[key].push(value); + } + else { + o[key] = [ o[key], value ]; + } + } + + function aliasIsBoolean(key) { + return aliases[key].some(function (x) { + return flags.bools[x]; + }); + } + + 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]*)$/); + var key = m[1]; + var value = m[2]; + if (flags.bools[key]) { + value = value !== 'false'; + } + setArg(key, value, arg); + } + else if (/^--no-.+/.test(arg)) { + var key = arg.match(/^--no-(.+)/)[1]; + setArg(key, false, arg); + } + else if (/^--.+/.test(arg)) { + var key = arg.match(/^--(.+)/)[1]; + var next = args[i + 1]; + if (next !== undefined && !/^-/.test(next) + && !flags.bools[key] + && !flags.allBools + && (aliases[key] ? !aliasIsBoolean(key) : true)) { + setArg(key, next, arg); + i++; + } + else if (/^(true|false)$/.test(next)) { + setArg(key, next === 'true', arg); + i++; + } + else { + setArg(key, flags.strings[key] ? '' : true, arg); + } + } + 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, arg) + continue; + } + + if (/[A-Za-z]/.test(letters[j]) && /=/.test(next)) { + setArg(letters[j], next.split('=')[1], arg); + broken = true; + break; + } + + if (/[A-Za-z]/.test(letters[j]) + && /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) { + setArg(letters[j], next, arg); + broken = true; + break; + } + + if (letters[j+1] && letters[j+1].match(/\W/)) { + setArg(letters[j], arg.slice(j+2), arg); + broken = true; + break; + } + else { + setArg(letters[j], flags.strings[letters[j]] ? '' : true, arg); + } + } + + var key = arg.slice(-1)[0]; + if (!broken && key !== '-') { + if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1]) + && !flags.bools[key] + && (aliases[key] ? !aliasIsBoolean(key) : true)) { + setArg(key, args[i+1], arg); + i++; + } + else if (args[i+1] && /^(true|false)$/.test(args[i+1])) { + setArg(key, args[i+1] === 'true', arg); + i++; + } + else { + setArg(key, flags.strings[key] ? '' : true, arg); + } + } + } + else { + if (!flags.unknownFn || flags.unknownFn(arg) !== false) { + argv._.push( + flags.strings['_'] || !isNumber(arg) ? arg : Number(arg) + ); + } + if (opts.stopEarly) { + argv._.push.apply(argv._, args.slice(i + 1)); + break; + } + } + } + + 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]); + }); + } + }); + + if (opts['--']) { + argv['--'] = new Array(); + notFlags.forEach(function(key) { + argv['--'].push(key); + }); + } + else { + 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 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); +} + diff --git a/node_modules/minimist/package.json b/node_modules/minimist/package.json new file mode 100644 index 0000000..c01937a --- /dev/null +++ b/node_modules/minimist/package.json @@ -0,0 +1,73 @@ +{ + "_from": "minimist@^1.2.5", + "_id": "minimist@1.2.5", + "_inBundle": false, + "_integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "_location": "/minimist", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "minimist@^1.2.5", + "name": "minimist", + "escapedName": "minimist", + "rawSpec": "^1.2.5", + "saveSpec": null, + "fetchSpec": "^1.2.5" + }, + "_requiredBy": [ + "/web-push" + ], + "_resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "_shasum": "67d66014b66a6a8aaa0c083c5fd58df4e4e97602", + "_spec": "minimist@^1.2.5", + "_where": "D:\\Users\\user\\Documents\\Portofolio\\Github\\WebsiteFootballPWA\\node_modules\\web-push", + "author": { + "name": "James Halliday", + "email": "mail@substack.net", + "url": "http://substack.net" + }, + "bugs": { + "url": "https://github.com/substack/minimist/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "parse argument options", + "devDependencies": { + "covert": "^1.0.0", + "tap": "~0.4.0", + "tape": "^3.5.0" + }, + "homepage": "https://github.com/substack/minimist", + "keywords": [ + "argv", + "getopt", + "parser", + "optimist" + ], + "license": "MIT", + "main": "index.js", + "name": "minimist", + "repository": { + "type": "git", + "url": "git://github.com/substack/minimist.git" + }, + "scripts": { + "coverage": "covert test/*.js", + "test": "tap test/*.js" + }, + "testling": { + "files": "test/*.js", + "browsers": [ + "ie/6..latest", + "ff/5", + "firefox/latest", + "chrome/10", + "chrome/latest", + "safari/5.1", + "safari/latest", + "opera/12" + ] + }, + "version": "1.2.5" +} diff --git a/node_modules/minimist/readme.markdown b/node_modules/minimist/readme.markdown new file mode 100644 index 0000000..5fd97ab --- /dev/null +++ b/node_modules/minimist/readme.markdown @@ -0,0 +1,95 @@ +# minimist + +parse argument options + +This module is the guts of optimist's argument parser without all the +fanciful decoration. + +# example + +``` js +var argv = require('minimist')(process.argv.slice(2)); +console.log(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' } +``` + +# security + +Previous versions had a prototype pollution bug that could cause privilege +escalation in some circumstances when handling untrusted user input. + +Please use version 1.2.3 or later: https://snyk.io/vuln/SNYK-JS-MINIMIST-559764 + +# 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 boolean, string or array of strings to always treat as +booleans. if `true` will treat all double hyphenated arguments without equal signs +as boolean (e.g. affects `--foo`, not `-f` or `--foo=bar`) +* `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 +* `opts.stopEarly` - when true, populate `argv._` with everything after the +first non-option +* `opts['--']` - when true, populate `argv._` with everything before the `--` +and `argv['--']` with everything after the `--`. Here's an example: + + ``` + > require('./')('one two three -- four five --six'.split(' '), { '--': true }) + { _: [ 'one', 'two', 'three' ], + '--': [ 'four', 'five', '--six' ] } + ``` + + Note that with `opts['--']` set, parsing for arguments still stops after the + `--`. + +* `opts.unknown` - a function which is invoked with a command line parameter not +defined in the `opts` configuration object. If the function returns `false`, the +unknown option is not added to `argv`. + +# install + +With [npm](https://npmjs.org) do: + +``` +npm install minimist +``` + +# license + +MIT diff --git a/node_modules/minimist/test/all_bool.js b/node_modules/minimist/test/all_bool.js new file mode 100644 index 0000000..ac83548 --- /dev/null +++ b/node_modules/minimist/test/all_bool.js @@ -0,0 +1,32 @@ +var parse = require('../'); +var test = require('tape'); + +test('flag boolean true (default all --args to boolean)', function (t) { + var argv = parse(['moo', '--honk', 'cow'], { + boolean: true + }); + + t.deepEqual(argv, { + honk: true, + _: ['moo', 'cow'] + }); + + t.deepEqual(typeof argv.honk, 'boolean'); + t.end(); +}); + +test('flag boolean true only affects double hyphen arguments without equals signs', function (t) { + var argv = parse(['moo', '--honk', 'cow', '-p', '55', '--tacos=good'], { + boolean: true + }); + + t.deepEqual(argv, { + honk: true, + tacos: 'good', + p: 55, + _: ['moo', 'cow'] + }); + + t.deepEqual(typeof argv.honk, 'boolean'); + t.end(); +}); diff --git a/node_modules/minimist/test/bool.js b/node_modules/minimist/test/bool.js new file mode 100644 index 0000000..5f7dbde --- /dev/null +++ b/node_modules/minimist/test/bool.js @@ -0,0 +1,178 @@ +var parse = require('../'); +var test = require('tape'); + +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('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 array with options hash', function (t) { + var aliased = [ '-h', 'derp' ]; + var regular = [ '--herp', 'derp' ]; + var alt = [ '--harp', 'derp' ]; + var opts = { + alias: { 'h': ['herp', 'harp'] }, + boolean: 'h' + }; + var aliasedArgv = parse(aliased, opts); + var propertyArgv = parse(regular, opts); + var altPropertyArgv = parse(alt, opts); + var expected = { + harp: true, + herp: true, + h: true, + '_': [ 'derp' ] + }; + t.same(aliasedArgv, expected); + t.same(propertyArgv, expected); + t.same(altPropertyArgv, 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(); +}); + +test('boolean --boool=true', function (t) { + var parsed = parse(['--boool=true'], { + default: { + boool: false + }, + boolean: ['boool'] + }); + + t.same(parsed.boool, true); + t.end(); +}); + +test('boolean --boool=false', function (t) { + var parsed = parse(['--boool=false'], { + default: { + boool: true + }, + boolean: ['boool'] + }); + + t.same(parsed.boool, false); + t.end(); +}); + +test('boolean using something similar to true', function (t) { + var opts = { boolean: 'h' }; + var result = parse(['-h', 'true.txt'], opts); + var expected = { + h: true, + '_': ['true.txt'] + }; + + t.same(result, expected); + t.end(); +}); \ No newline at end of file diff --git a/node_modules/minimist/test/dash.js b/node_modules/minimist/test/dash.js new file mode 100644 index 0000000..5a4fa5b --- /dev/null +++ b/node_modules/minimist/test/dash.js @@ -0,0 +1,31 @@ +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' ] }); +}); + +test('move arguments after the -- into their own `--` array', function(t) { + t.plan(1); + t.deepEqual( + parse([ '--name', 'John', 'before', '--', 'after' ], { '--': true }), + { name: 'John', _: [ 'before' ], '--': [ 'after' ] }); +}); diff --git a/node_modules/minimist/test/default_bool.js b/node_modules/minimist/test/default_bool.js new file mode 100644 index 0000000..780a311 --- /dev/null +++ b/node_modules/minimist/test/default_bool.js @@ -0,0 +1,35 @@ +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(); +}); + +test('boolean default to null', function (t) { + var argv = parse([], { + boolean: 'maybe', + default: { maybe: null } + }); + t.equal(argv.maybe, null); + var argv = parse(['--maybe'], { + boolean: 'maybe', + default: { maybe: null } + }); + t.equal(argv.maybe, true); + t.end(); + +}) diff --git a/node_modules/minimist/test/dotted.js b/node_modules/minimist/test/dotted.js new file mode 100644 index 0000000..d8b3e85 --- /dev/null +++ b/node_modules/minimist/test/dotted.js @@ -0,0 +1,22 @@ +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(); +}); + +test('dotted default with no alias', function (t) { + var argv = parse('', {default: {'a.b': 11}}); + t.equal(argv.a.b, 11); + t.end(); +}); diff --git a/node_modules/minimist/test/kv_short.js b/node_modules/minimist/test/kv_short.js new file mode 100644 index 0000000..f813b30 --- /dev/null +++ b/node_modules/minimist/test/kv_short.js @@ -0,0 +1,16 @@ +var parse = require('../'); +var test = require('tape'); + +test('short -k=v' , function (t) { + t.plan(1); + + var argv = parse([ '-b=123' ]); + t.deepEqual(argv, { b: 123, _: [] }); +}); + +test('multi short -k=v' , function (t) { + t.plan(1); + + var argv = parse([ '-a=whatever', '-b=robots' ]); + t.deepEqual(argv, { a: 'whatever', b: 'robots', _: [] }); +}); diff --git a/node_modules/minimist/test/long.js b/node_modules/minimist/test/long.js new file mode 100644 index 0000000..5d3a1e0 --- /dev/null +++ b/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/node_modules/minimist/test/num.js b/node_modules/minimist/test/num.js new file mode 100644 index 0000000..2cc77f4 --- /dev/null +++ b/node_modules/minimist/test/num.js @@ -0,0 +1,36 @@ +var parse = require('../'); +var test = require('tape'); + +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('already a number', function (t) { + var argv = parse([ '-x', 1234, 789 ]); + t.deepEqual(argv, { x : 1234, _ : [ 789 ] }); + t.deepEqual(typeof argv.x, 'number'); + t.deepEqual(typeof argv._[0], 'number'); + t.end(); +}); diff --git a/node_modules/minimist/test/parse.js b/node_modules/minimist/test/parse.js new file mode 100644 index 0000000..7b4a2a1 --- /dev/null +++ b/node_modules/minimist/test/parse.js @@ -0,0 +1,197 @@ +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('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('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('string and alias', function(t) { + var x = parse([ '--str', '000123' ], { + string: 's', + alias: { s: 'str' } + }); + + t.equal(x.str, '000123'); + t.equal(typeof x.str, 'string'); + t.equal(x.s, '000123'); + t.equal(typeof x.s, 'string'); + + var y = parse([ '-s', '000123' ], { + string: 'str', + alias: { str: 's' } + }); + + t.equal(y.str, '000123'); + t.equal(typeof y.str, 'string'); + t.equal(y.s, '000123'); + t.equal(typeof y.s, 'string'); + 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(); +}); diff --git a/node_modules/minimist/test/parse_modified.js b/node_modules/minimist/test/parse_modified.js new file mode 100644 index 0000000..ab620dc --- /dev/null +++ b/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/node_modules/minimist/test/proto.js b/node_modules/minimist/test/proto.js new file mode 100644 index 0000000..8649107 --- /dev/null +++ b/node_modules/minimist/test/proto.js @@ -0,0 +1,44 @@ +var parse = require('../'); +var test = require('tape'); + +test('proto pollution', function (t) { + var argv = parse(['--__proto__.x','123']); + t.equal({}.x, undefined); + t.equal(argv.__proto__.x, undefined); + t.equal(argv.x, undefined); + t.end(); +}); + +test('proto pollution (array)', function (t) { + var argv = parse(['--x','4','--x','5','--x.__proto__.z','789']); + t.equal({}.z, undefined); + t.deepEqual(argv.x, [4,5]); + t.equal(argv.x.z, undefined); + t.equal(argv.x.__proto__.z, undefined); + t.end(); +}); + +test('proto pollution (number)', function (t) { + var argv = parse(['--x','5','--x.__proto__.z','100']); + t.equal({}.z, undefined); + t.equal((4).z, undefined); + t.equal(argv.x, 5); + t.equal(argv.x.z, undefined); + t.end(); +}); + +test('proto pollution (string)', function (t) { + var argv = parse(['--x','abc','--x.__proto__.z','def']); + t.equal({}.z, undefined); + t.equal('...'.z, undefined); + t.equal(argv.x, 'abc'); + t.equal(argv.x.z, undefined); + t.end(); +}); + +test('proto pollution (constructor)', function (t) { + var argv = parse(['--constructor.prototype.y','123']); + t.equal({}.y, undefined); + t.equal(argv.y, undefined); + t.end(); +}); diff --git a/node_modules/minimist/test/short.js b/node_modules/minimist/test/short.js new file mode 100644 index 0000000..d513a1c --- /dev/null +++ b/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/node_modules/minimist/test/stop_early.js b/node_modules/minimist/test/stop_early.js new file mode 100644 index 0000000..bdf9fbc --- /dev/null +++ b/node_modules/minimist/test/stop_early.js @@ -0,0 +1,15 @@ +var parse = require('../'); +var test = require('tape'); + +test('stops parsing on the first non-option when stopEarly is set', function (t) { + var argv = parse(['--aaa', 'bbb', 'ccc', '--ddd'], { + stopEarly: true + }); + + t.deepEqual(argv, { + aaa: 'bbb', + _: ['ccc', '--ddd'] + }); + + t.end(); +}); diff --git a/node_modules/minimist/test/unknown.js b/node_modules/minimist/test/unknown.js new file mode 100644 index 0000000..462a36b --- /dev/null +++ b/node_modules/minimist/test/unknown.js @@ -0,0 +1,102 @@ +var parse = require('../'); +var test = require('tape'); + +test('boolean and alias is not unknown', function (t) { + var unknown = []; + function unknownFn(arg) { + unknown.push(arg); + return false; + } + var aliased = [ '-h', 'true', '--derp', 'true' ]; + var regular = [ '--herp', 'true', '-d', 'true' ]; + var opts = { + alias: { h: 'herp' }, + boolean: 'h', + unknown: unknownFn + }; + var aliasedArgv = parse(aliased, opts); + var propertyArgv = parse(regular, opts); + + t.same(unknown, ['--derp', '-d']); + t.end(); +}); + +test('flag boolean true any double hyphen argument is not unknown', function (t) { + var unknown = []; + function unknownFn(arg) { + unknown.push(arg); + return false; + } + var argv = parse(['--honk', '--tacos=good', 'cow', '-p', '55'], { + boolean: true, + unknown: unknownFn + }); + t.same(unknown, ['--tacos=good', 'cow', '-p']); + t.same(argv, { + honk: true, + _: [] + }); + t.end(); +}); + +test('string and alias is not unknown', function (t) { + var unknown = []; + function unknownFn(arg) { + unknown.push(arg); + return false; + } + var aliased = [ '-h', 'hello', '--derp', 'goodbye' ]; + var regular = [ '--herp', 'hello', '-d', 'moon' ]; + var opts = { + alias: { h: 'herp' }, + string: 'h', + unknown: unknownFn + }; + var aliasedArgv = parse(aliased, opts); + var propertyArgv = parse(regular, opts); + + t.same(unknown, ['--derp', '-d']); + t.end(); +}); + +test('default and alias is not unknown', function (t) { + var unknown = []; + function unknownFn(arg) { + unknown.push(arg); + return false; + } + var aliased = [ '-h', 'hello' ]; + var regular = [ '--herp', 'hello' ]; + var opts = { + default: { 'h': 'bar' }, + alias: { 'h': 'herp' }, + unknown: unknownFn + }; + var aliasedArgv = parse(aliased, opts); + var propertyArgv = parse(regular, opts); + + t.same(unknown, []); + t.end(); + unknownFn(); // exercise fn for 100% coverage +}); + +test('value following -- is not unknown', function (t) { + var unknown = []; + function unknownFn(arg) { + unknown.push(arg); + return false; + } + var aliased = [ '--bad', '--', 'good', 'arg' ]; + var opts = { + '--': true, + unknown: unknownFn + }; + var argv = parse(aliased, opts); + + t.same(unknown, ['--bad']); + t.same(argv, { + '--': ['good', 'arg'], + '_': [] + }) + t.end(); +}); diff --git a/node_modules/minimist/test/whitespace.js b/node_modules/minimist/test/whitespace.js new file mode 100644 index 0000000..8a52a58 --- /dev/null +++ b/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/node_modules/ms/index.js b/node_modules/ms/index.js new file mode 100644 index 0000000..c4498bc --- /dev/null +++ b/node_modules/ms/index.js @@ -0,0 +1,162 @@ +/** + * Helpers. + */ + +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; +var w = d * 7; +var y = d * 365.25; + +/** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} [options] + * @throws {Error} throw an error if val is not a non-empty string or a number + * @return {String|Number} + * @api public + */ + +module.exports = function(val, options) { + options = options || {}; + var type = typeof val; + if (type === 'string' && val.length > 0) { + return parse(val); + } else if (type === 'number' && isFinite(val)) { + return options.long ? fmtLong(val) : fmtShort(val); + } + throw new Error( + 'val is not a non-empty string or a valid number. val=' + + JSON.stringify(val) + ); +}; + +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function parse(str) { + str = String(str); + if (str.length > 100) { + return; + } + var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec( + str + ); + if (!match) { + return; + } + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'yrs': + case 'yr': + case 'y': + return n * y; + case 'weeks': + case 'week': + case 'w': + return n * w; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'hrs': + case 'hr': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'mins': + case 'min': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 'secs': + case 'sec': + case 's': + return n * s; + case 'milliseconds': + case 'millisecond': + case 'msecs': + case 'msec': + case 'ms': + return n; + default: + return undefined; + } +} + +/** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtShort(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return Math.round(ms / d) + 'd'; + } + if (msAbs >= h) { + return Math.round(ms / h) + 'h'; + } + if (msAbs >= m) { + return Math.round(ms / m) + 'm'; + } + if (msAbs >= s) { + return Math.round(ms / s) + 's'; + } + return ms + 'ms'; +} + +/** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtLong(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return plural(ms, msAbs, d, 'day'); + } + if (msAbs >= h) { + return plural(ms, msAbs, h, 'hour'); + } + if (msAbs >= m) { + return plural(ms, msAbs, m, 'minute'); + } + if (msAbs >= s) { + return plural(ms, msAbs, s, 'second'); + } + return ms + ' ms'; +} + +/** + * Pluralization helper. + */ + +function plural(ms, msAbs, n, name) { + var isPlural = msAbs >= n * 1.5; + return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : ''); +} diff --git a/node_modules/ms/license.md b/node_modules/ms/license.md new file mode 100644 index 0000000..69b6125 --- /dev/null +++ b/node_modules/ms/license.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Zeit, 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/node_modules/ms/package.json b/node_modules/ms/package.json new file mode 100644 index 0000000..cfb60f5 --- /dev/null +++ b/node_modules/ms/package.json @@ -0,0 +1,69 @@ +{ + "_from": "ms@2.1.2", + "_id": "ms@2.1.2", + "_inBundle": false, + "_integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "_location": "/ms", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "ms@2.1.2", + "name": "ms", + "escapedName": "ms", + "rawSpec": "2.1.2", + "saveSpec": null, + "fetchSpec": "2.1.2" + }, + "_requiredBy": [ + "/debug" + ], + "_resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "_shasum": "d09d1f357b443f493382a8eb3ccd183872ae6009", + "_spec": "ms@2.1.2", + "_where": "D:\\Users\\user\\Documents\\Portofolio\\Github\\WebsiteFootballPWA\\node_modules\\debug", + "bugs": { + "url": "https://github.com/zeit/ms/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Tiny millisecond conversion utility", + "devDependencies": { + "eslint": "4.12.1", + "expect.js": "0.3.1", + "husky": "0.14.3", + "lint-staged": "5.0.0", + "mocha": "4.0.1" + }, + "eslintConfig": { + "extends": "eslint:recommended", + "env": { + "node": true, + "es6": true + } + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/zeit/ms#readme", + "license": "MIT", + "lint-staged": { + "*.js": [ + "npm run lint", + "prettier --single-quote --write", + "git add" + ] + }, + "main": "./index", + "name": "ms", + "repository": { + "type": "git", + "url": "git+https://github.com/zeit/ms.git" + }, + "scripts": { + "lint": "eslint lib/* bin/*", + "precommit": "lint-staged", + "test": "mocha tests.js" + }, + "version": "2.1.2" +} diff --git a/node_modules/ms/readme.md b/node_modules/ms/readme.md new file mode 100644 index 0000000..9a1996b --- /dev/null +++ b/node_modules/ms/readme.md @@ -0,0 +1,60 @@ +# ms + +[![Build Status](https://travis-ci.org/zeit/ms.svg?branch=master)](https://travis-ci.org/zeit/ms) +[![Join the community on Spectrum](https://withspectrum.github.io/badge/badge.svg)](https://spectrum.chat/zeit) + +Use this package to easily convert various time formats to milliseconds. + +## Examples + +```js +ms('2 days') // 172800000 +ms('1d') // 86400000 +ms('10h') // 36000000 +ms('2.5 hrs') // 9000000 +ms('2h') // 7200000 +ms('1m') // 60000 +ms('5s') // 5000 +ms('1y') // 31557600000 +ms('100') // 100 +ms('-3 days') // -259200000 +ms('-1h') // -3600000 +ms('-200') // -200 +``` + +### Convert from Milliseconds + +```js +ms(60000) // "1m" +ms(2 * 60000) // "2m" +ms(-3 * 60000) // "-3m" +ms(ms('10 hours')) // "10h" +``` + +### Time Format Written-Out + +```js +ms(60000, { long: true }) // "1 minute" +ms(2 * 60000, { long: true }) // "2 minutes" +ms(-3 * 60000, { long: true }) // "-3 minutes" +ms(ms('10 hours'), { long: true }) // "10 hours" +``` + +## Features + +- Works both in [Node.js](https://nodejs.org) and in the browser +- If a number is supplied to `ms`, a string with a unit is returned +- If a string that contains the number is supplied, it returns it as a number (e.g.: it returns `100` for `'100'`) +- If you pass a string with a number and a valid unit, the number of equivalent milliseconds is returned + +## Related Packages + +- [ms.macro](https://github.com/knpwrs/ms.macro) - Run `ms` as a macro at build-time. + +## Caught a Bug? + +1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device +2. Link the package to the global module directory: `npm link` +3. Within the module you want to test your local development instance of ms, just link it to the dependencies: `npm link ms`. Instead of the default one from npm, Node.js will now use your clone of ms! + +As always, you can run the tests using: `npm test` diff --git a/node_modules/safe-buffer/LICENSE b/node_modules/safe-buffer/LICENSE new file mode 100644 index 0000000..0c068ce --- /dev/null +++ b/node_modules/safe-buffer/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) Feross Aboukhadijeh + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/safe-buffer/README.md b/node_modules/safe-buffer/README.md new file mode 100644 index 0000000..e9a81af --- /dev/null +++ b/node_modules/safe-buffer/README.md @@ -0,0 +1,584 @@ +# safe-buffer [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![javascript style guide][standard-image]][standard-url] + +[travis-image]: https://img.shields.io/travis/feross/safe-buffer/master.svg +[travis-url]: https://travis-ci.org/feross/safe-buffer +[npm-image]: https://img.shields.io/npm/v/safe-buffer.svg +[npm-url]: https://npmjs.org/package/safe-buffer +[downloads-image]: https://img.shields.io/npm/dm/safe-buffer.svg +[downloads-url]: https://npmjs.org/package/safe-buffer +[standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg +[standard-url]: https://standardjs.com + +#### Safer Node.js Buffer API + +**Use the new Node.js Buffer APIs (`Buffer.from`, `Buffer.alloc`, +`Buffer.allocUnsafe`, `Buffer.allocUnsafeSlow`) in all versions of Node.js.** + +**Uses the built-in implementation when available.** + +## install + +``` +npm install safe-buffer +``` + +## usage + +The goal of this package is to provide a safe replacement for the node.js `Buffer`. + +It's a drop-in replacement for `Buffer`. You can use it by adding one `require` line to +the top of your node.js modules: + +```js +var Buffer = require('safe-buffer').Buffer + +// Existing buffer code will continue to work without issues: + +new Buffer('hey', 'utf8') +new Buffer([1, 2, 3], 'utf8') +new Buffer(obj) +new Buffer(16) // create an uninitialized buffer (potentially unsafe) + +// But you can use these new explicit APIs to make clear what you want: + +Buffer.from('hey', 'utf8') // convert from many types to a Buffer +Buffer.alloc(16) // create a zero-filled buffer (safe) +Buffer.allocUnsafe(16) // create an uninitialized buffer (potentially unsafe) +``` + +## api + +### Class Method: Buffer.from(array) + + +* `array` {Array} + +Allocates a new `Buffer` using an `array` of octets. + +```js +const buf = Buffer.from([0x62,0x75,0x66,0x66,0x65,0x72]); + // creates a new Buffer containing ASCII bytes + // ['b','u','f','f','e','r'] +``` + +A `TypeError` will be thrown if `array` is not an `Array`. + +### Class Method: Buffer.from(arrayBuffer[, byteOffset[, length]]) + + +* `arrayBuffer` {ArrayBuffer} The `.buffer` property of a `TypedArray` or + a `new ArrayBuffer()` +* `byteOffset` {Number} Default: `0` +* `length` {Number} Default: `arrayBuffer.length - byteOffset` + +When passed a reference to the `.buffer` property of a `TypedArray` instance, +the newly created `Buffer` will share the same allocated memory as the +TypedArray. + +```js +const arr = new Uint16Array(2); +arr[0] = 5000; +arr[1] = 4000; + +const buf = Buffer.from(arr.buffer); // shares the memory with arr; + +console.log(buf); + // Prints: + +// changing the TypedArray changes the Buffer also +arr[1] = 6000; + +console.log(buf); + // Prints: +``` + +The optional `byteOffset` and `length` arguments specify a memory range within +the `arrayBuffer` that will be shared by the `Buffer`. + +```js +const ab = new ArrayBuffer(10); +const buf = Buffer.from(ab, 0, 2); +console.log(buf.length); + // Prints: 2 +``` + +A `TypeError` will be thrown if `arrayBuffer` is not an `ArrayBuffer`. + +### Class Method: Buffer.from(buffer) + + +* `buffer` {Buffer} + +Copies the passed `buffer` data onto a new `Buffer` instance. + +```js +const buf1 = Buffer.from('buffer'); +const buf2 = Buffer.from(buf1); + +buf1[0] = 0x61; +console.log(buf1.toString()); + // 'auffer' +console.log(buf2.toString()); + // 'buffer' (copy is not changed) +``` + +A `TypeError` will be thrown if `buffer` is not a `Buffer`. + +### Class Method: Buffer.from(str[, encoding]) + + +* `str` {String} String to encode. +* `encoding` {String} Encoding to use, Default: `'utf8'` + +Creates a new `Buffer` containing the given JavaScript string `str`. If +provided, the `encoding` parameter identifies the character encoding. +If not provided, `encoding` defaults to `'utf8'`. + +```js +const buf1 = Buffer.from('this is a tést'); +console.log(buf1.toString()); + // prints: this is a tést +console.log(buf1.toString('ascii')); + // prints: this is a tC)st + +const buf2 = Buffer.from('7468697320697320612074c3a97374', 'hex'); +console.log(buf2.toString()); + // prints: this is a tést +``` + +A `TypeError` will be thrown if `str` is not a string. + +### Class Method: Buffer.alloc(size[, fill[, encoding]]) + + +* `size` {Number} +* `fill` {Value} Default: `undefined` +* `encoding` {String} Default: `utf8` + +Allocates a new `Buffer` of `size` bytes. If `fill` is `undefined`, the +`Buffer` will be *zero-filled*. + +```js +const buf = Buffer.alloc(5); +console.log(buf); + // +``` + +The `size` must be less than or equal to the value of +`require('buffer').kMaxLength` (on 64-bit architectures, `kMaxLength` is +`(2^31)-1`). Otherwise, a [`RangeError`][] is thrown. A zero-length Buffer will +be created if a `size` less than or equal to 0 is specified. + +If `fill` is specified, the allocated `Buffer` will be initialized by calling +`buf.fill(fill)`. See [`buf.fill()`][] for more information. + +```js +const buf = Buffer.alloc(5, 'a'); +console.log(buf); + // +``` + +If both `fill` and `encoding` are specified, the allocated `Buffer` will be +initialized by calling `buf.fill(fill, encoding)`. For example: + +```js +const buf = Buffer.alloc(11, 'aGVsbG8gd29ybGQ=', 'base64'); +console.log(buf); + // +``` + +Calling `Buffer.alloc(size)` can be significantly slower than the alternative +`Buffer.allocUnsafe(size)` but ensures that the newly created `Buffer` instance +contents will *never contain sensitive data*. + +A `TypeError` will be thrown if `size` is not a number. + +### Class Method: Buffer.allocUnsafe(size) + + +* `size` {Number} + +Allocates a new *non-zero-filled* `Buffer` of `size` bytes. The `size` must +be less than or equal to the value of `require('buffer').kMaxLength` (on 64-bit +architectures, `kMaxLength` is `(2^31)-1`). Otherwise, a [`RangeError`][] is +thrown. A zero-length Buffer will be created if a `size` less than or equal to +0 is specified. + +The underlying memory for `Buffer` instances created in this way is *not +initialized*. The contents of the newly created `Buffer` are unknown and +*may contain sensitive data*. Use [`buf.fill(0)`][] to initialize such +`Buffer` instances to zeroes. + +```js +const buf = Buffer.allocUnsafe(5); +console.log(buf); + // + // (octets will be different, every time) +buf.fill(0); +console.log(buf); + // +``` + +A `TypeError` will be thrown if `size` is not a number. + +Note that the `Buffer` module pre-allocates an internal `Buffer` instance of +size `Buffer.poolSize` that is used as a pool for the fast allocation of new +`Buffer` instances created using `Buffer.allocUnsafe(size)` (and the deprecated +`new Buffer(size)` constructor) only when `size` is less than or equal to +`Buffer.poolSize >> 1` (floor of `Buffer.poolSize` divided by two). The default +value of `Buffer.poolSize` is `8192` but can be modified. + +Use of this pre-allocated internal memory pool is a key difference between +calling `Buffer.alloc(size, fill)` vs. `Buffer.allocUnsafe(size).fill(fill)`. +Specifically, `Buffer.alloc(size, fill)` will *never* use the internal Buffer +pool, while `Buffer.allocUnsafe(size).fill(fill)` *will* use the internal +Buffer pool if `size` is less than or equal to half `Buffer.poolSize`. The +difference is subtle but can be important when an application requires the +additional performance that `Buffer.allocUnsafe(size)` provides. + +### Class Method: Buffer.allocUnsafeSlow(size) + + +* `size` {Number} + +Allocates a new *non-zero-filled* and non-pooled `Buffer` of `size` bytes. The +`size` must be less than or equal to the value of +`require('buffer').kMaxLength` (on 64-bit architectures, `kMaxLength` is +`(2^31)-1`). Otherwise, a [`RangeError`][] is thrown. A zero-length Buffer will +be created if a `size` less than or equal to 0 is specified. + +The underlying memory for `Buffer` instances created in this way is *not +initialized*. The contents of the newly created `Buffer` are unknown and +*may contain sensitive data*. Use [`buf.fill(0)`][] to initialize such +`Buffer` instances to zeroes. + +When using `Buffer.allocUnsafe()` to allocate new `Buffer` instances, +allocations under 4KB are, by default, sliced from a single pre-allocated +`Buffer`. This allows applications to avoid the garbage collection overhead of +creating many individually allocated Buffers. This approach improves both +performance and memory usage by eliminating the need to track and cleanup as +many `Persistent` objects. + +However, in the case where a developer may need to retain a small chunk of +memory from a pool for an indeterminate amount of time, it may be appropriate +to create an un-pooled Buffer instance using `Buffer.allocUnsafeSlow()` then +copy out the relevant bits. + +```js +// need to keep around a few small chunks of memory +const store = []; + +socket.on('readable', () => { + const data = socket.read(); + // allocate for retained data + const sb = Buffer.allocUnsafeSlow(10); + // copy the data into the new allocation + data.copy(sb, 0, 0, 10); + store.push(sb); +}); +``` + +Use of `Buffer.allocUnsafeSlow()` should be used only as a last resort *after* +a developer has observed undue memory retention in their applications. + +A `TypeError` will be thrown if `size` is not a number. + +### All the Rest + +The rest of the `Buffer` API is exactly the same as in node.js. +[See the docs](https://nodejs.org/api/buffer.html). + + +## Related links + +- [Node.js issue: Buffer(number) is unsafe](https://github.com/nodejs/node/issues/4660) +- [Node.js Enhancement Proposal: Buffer.from/Buffer.alloc/Buffer.zalloc/Buffer() soft-deprecate](https://github.com/nodejs/node-eps/pull/4) + +## Why is `Buffer` unsafe? + +Today, the node.js `Buffer` constructor is overloaded to handle many different argument +types like `String`, `Array`, `Object`, `TypedArrayView` (`Uint8Array`, etc.), +`ArrayBuffer`, and also `Number`. + +The API is optimized for convenience: you can throw any type at it, and it will try to do +what you want. + +Because the Buffer constructor is so powerful, you often see code like this: + +```js +// Convert UTF-8 strings to hex +function toHex (str) { + return new Buffer(str).toString('hex') +} +``` + +***But what happens if `toHex` is called with a `Number` argument?*** + +### Remote Memory Disclosure + +If an attacker can make your program call the `Buffer` constructor with a `Number` +argument, then they can make it allocate uninitialized memory from the node.js process. +This could potentially disclose TLS private keys, user data, or database passwords. + +When the `Buffer` constructor is passed a `Number` argument, it returns an +**UNINITIALIZED** block of memory of the specified `size`. When you create a `Buffer` like +this, you **MUST** overwrite the contents before returning it to the user. + +From the [node.js docs](https://nodejs.org/api/buffer.html#buffer_new_buffer_size): + +> `new Buffer(size)` +> +> - `size` Number +> +> The underlying memory for `Buffer` instances created in this way is not initialized. +> **The contents of a newly created `Buffer` are unknown and could contain sensitive +> data.** Use `buf.fill(0)` to initialize a Buffer to zeroes. + +(Emphasis our own.) + +Whenever the programmer intended to create an uninitialized `Buffer` you often see code +like this: + +```js +var buf = new Buffer(16) + +// Immediately overwrite the uninitialized buffer with data from another buffer +for (var i = 0; i < buf.length; i++) { + buf[i] = otherBuf[i] +} +``` + + +### Would this ever be a problem in real code? + +Yes. It's surprisingly common to forget to check the type of your variables in a +dynamically-typed language like JavaScript. + +Usually the consequences of assuming the wrong type is that your program crashes with an +uncaught exception. But the failure mode for forgetting to check the type of arguments to +the `Buffer` constructor is more catastrophic. + +Here's an example of a vulnerable service that takes a JSON payload and converts it to +hex: + +```js +// Take a JSON payload {str: "some string"} and convert it to hex +var server = http.createServer(function (req, res) { + var data = '' + req.setEncoding('utf8') + req.on('data', function (chunk) { + data += chunk + }) + req.on('end', function () { + var body = JSON.parse(data) + res.end(new Buffer(body.str).toString('hex')) + }) +}) + +server.listen(8080) +``` + +In this example, an http client just has to send: + +```json +{ + "str": 1000 +} +``` + +and it will get back 1,000 bytes of uninitialized memory from the server. + +This is a very serious bug. It's similar in severity to the +[the Heartbleed bug](http://heartbleed.com/) that allowed disclosure of OpenSSL process +memory by remote attackers. + + +### Which real-world packages were vulnerable? + +#### [`bittorrent-dht`](https://www.npmjs.com/package/bittorrent-dht) + +[Mathias Buus](https://github.com/mafintosh) and I +([Feross Aboukhadijeh](http://feross.org/)) found this issue in one of our own packages, +[`bittorrent-dht`](https://www.npmjs.com/package/bittorrent-dht). The bug would allow +anyone on the internet to send a series of messages to a user of `bittorrent-dht` and get +them to reveal 20 bytes at a time of uninitialized memory from the node.js process. + +Here's +[the commit](https://github.com/feross/bittorrent-dht/commit/6c7da04025d5633699800a99ec3fbadf70ad35b8) +that fixed it. We released a new fixed version, created a +[Node Security Project disclosure](https://nodesecurity.io/advisories/68), and deprecated all +vulnerable versions on npm so users will get a warning to upgrade to a newer version. + +#### [`ws`](https://www.npmjs.com/package/ws) + +That got us wondering if there were other vulnerable packages. Sure enough, within a short +period of time, we found the same issue in [`ws`](https://www.npmjs.com/package/ws), the +most popular WebSocket implementation in node.js. + +If certain APIs were called with `Number` parameters instead of `String` or `Buffer` as +expected, then uninitialized server memory would be disclosed to the remote peer. + +These were the vulnerable methods: + +```js +socket.send(number) +socket.ping(number) +socket.pong(number) +``` + +Here's a vulnerable socket server with some echo functionality: + +```js +server.on('connection', function (socket) { + socket.on('message', function (message) { + message = JSON.parse(message) + if (message.type === 'echo') { + socket.send(message.data) // send back the user's message + } + }) +}) +``` + +`socket.send(number)` called on the server, will disclose server memory. + +Here's [the release](https://github.com/websockets/ws/releases/tag/1.0.1) where the issue +was fixed, with a more detailed explanation. Props to +[Arnout Kazemier](https://github.com/3rd-Eden) for the quick fix. Here's the +[Node Security Project disclosure](https://nodesecurity.io/advisories/67). + + +### What's the solution? + +It's important that node.js offers a fast way to get memory otherwise performance-critical +applications would needlessly get a lot slower. + +But we need a better way to *signal our intent* as programmers. **When we want +uninitialized memory, we should request it explicitly.** + +Sensitive functionality should not be packed into a developer-friendly API that loosely +accepts many different types. This type of API encourages the lazy practice of passing +variables in without checking the type very carefully. + +#### A new API: `Buffer.allocUnsafe(number)` + +The functionality of creating buffers with uninitialized memory should be part of another +API. We propose `Buffer.allocUnsafe(number)`. This way, it's not part of an API that +frequently gets user input of all sorts of different types passed into it. + +```js +var buf = Buffer.allocUnsafe(16) // careful, uninitialized memory! + +// Immediately overwrite the uninitialized buffer with data from another buffer +for (var i = 0; i < buf.length; i++) { + buf[i] = otherBuf[i] +} +``` + + +### How do we fix node.js core? + +We sent [a PR to node.js core](https://github.com/nodejs/node/pull/4514) (merged as +`semver-major`) which defends against one case: + +```js +var str = 16 +new Buffer(str, 'utf8') +``` + +In this situation, it's implied that the programmer intended the first argument to be a +string, since they passed an encoding as a second argument. Today, node.js will allocate +uninitialized memory in the case of `new Buffer(number, encoding)`, which is probably not +what the programmer intended. + +But this is only a partial solution, since if the programmer does `new Buffer(variable)` +(without an `encoding` parameter) there's no way to know what they intended. If `variable` +is sometimes a number, then uninitialized memory will sometimes be returned. + +### What's the real long-term fix? + +We could deprecate and remove `new Buffer(number)` and use `Buffer.allocUnsafe(number)` when +we need uninitialized memory. But that would break 1000s of packages. + +~~We believe the best solution is to:~~ + +~~1. Change `new Buffer(number)` to return safe, zeroed-out memory~~ + +~~2. Create a new API for creating uninitialized Buffers. We propose: `Buffer.allocUnsafe(number)`~~ + +#### Update + +We now support adding three new APIs: + +- `Buffer.from(value)` - convert from any type to a buffer +- `Buffer.alloc(size)` - create a zero-filled buffer +- `Buffer.allocUnsafe(size)` - create an uninitialized buffer with given size + +This solves the core problem that affected `ws` and `bittorrent-dht` which is +`Buffer(variable)` getting tricked into taking a number argument. + +This way, existing code continues working and the impact on the npm ecosystem will be +minimal. Over time, npm maintainers can migrate performance-critical code to use +`Buffer.allocUnsafe(number)` instead of `new Buffer(number)`. + + +### Conclusion + +We think there's a serious design issue with the `Buffer` API as it exists today. It +promotes insecure software by putting high-risk functionality into a convenient API +with friendly "developer ergonomics". + +This wasn't merely a theoretical exercise because we found the issue in some of the +most popular npm packages. + +Fortunately, there's an easy fix that can be applied today. Use `safe-buffer` in place of +`buffer`. + +```js +var Buffer = require('safe-buffer').Buffer +``` + +Eventually, we hope that node.js core can switch to this new, safer behavior. We believe +the impact on the ecosystem would be minimal since it's not a breaking change. +Well-maintained, popular packages would be updated to use `Buffer.alloc` quickly, while +older, insecure packages would magically become safe from this attack vector. + + +## links + +- [Node.js PR: buffer: throw if both length and enc are passed](https://github.com/nodejs/node/pull/4514) +- [Node Security Project disclosure for `ws`](https://nodesecurity.io/advisories/67) +- [Node Security Project disclosure for`bittorrent-dht`](https://nodesecurity.io/advisories/68) + + +## credit + +The original issues in `bittorrent-dht` +([disclosure](https://nodesecurity.io/advisories/68)) and +`ws` ([disclosure](https://nodesecurity.io/advisories/67)) were discovered by +[Mathias Buus](https://github.com/mafintosh) and +[Feross Aboukhadijeh](http://feross.org/). + +Thanks to [Adam Baldwin](https://github.com/evilpacket) for helping disclose these issues +and for his work running the [Node Security Project](https://nodesecurity.io/). + +Thanks to [John Hiesey](https://github.com/jhiesey) for proofreading this README and +auditing the code. + + +## license + +MIT. Copyright (C) [Feross Aboukhadijeh](http://feross.org) diff --git a/node_modules/safe-buffer/index.d.ts b/node_modules/safe-buffer/index.d.ts new file mode 100644 index 0000000..e9fed80 --- /dev/null +++ b/node_modules/safe-buffer/index.d.ts @@ -0,0 +1,187 @@ +declare module "safe-buffer" { + export class Buffer { + length: number + write(string: string, offset?: number, length?: number, encoding?: string): number; + toString(encoding?: string, start?: number, end?: number): string; + toJSON(): { type: 'Buffer', data: any[] }; + equals(otherBuffer: Buffer): boolean; + compare(otherBuffer: Buffer, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number; + copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number; + slice(start?: number, end?: number): Buffer; + writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number; + readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number; + readIntLE(offset: number, byteLength: number, noAssert?: boolean): number; + readIntBE(offset: number, byteLength: number, noAssert?: boolean): number; + readUInt8(offset: number, noAssert?: boolean): number; + readUInt16LE(offset: number, noAssert?: boolean): number; + readUInt16BE(offset: number, noAssert?: boolean): number; + readUInt32LE(offset: number, noAssert?: boolean): number; + readUInt32BE(offset: number, noAssert?: boolean): number; + readInt8(offset: number, noAssert?: boolean): number; + readInt16LE(offset: number, noAssert?: boolean): number; + readInt16BE(offset: number, noAssert?: boolean): number; + readInt32LE(offset: number, noAssert?: boolean): number; + readInt32BE(offset: number, noAssert?: boolean): number; + readFloatLE(offset: number, noAssert?: boolean): number; + readFloatBE(offset: number, noAssert?: boolean): number; + readDoubleLE(offset: number, noAssert?: boolean): number; + readDoubleBE(offset: number, noAssert?: boolean): number; + swap16(): Buffer; + swap32(): Buffer; + swap64(): Buffer; + writeUInt8(value: number, offset: number, noAssert?: boolean): number; + writeUInt16LE(value: number, offset: number, noAssert?: boolean): number; + writeUInt16BE(value: number, offset: number, noAssert?: boolean): number; + writeUInt32LE(value: number, offset: number, noAssert?: boolean): number; + writeUInt32BE(value: number, offset: number, noAssert?: boolean): number; + writeInt8(value: number, offset: number, noAssert?: boolean): number; + writeInt16LE(value: number, offset: number, noAssert?: boolean): number; + writeInt16BE(value: number, offset: number, noAssert?: boolean): number; + writeInt32LE(value: number, offset: number, noAssert?: boolean): number; + writeInt32BE(value: number, offset: number, noAssert?: boolean): number; + writeFloatLE(value: number, offset: number, noAssert?: boolean): number; + writeFloatBE(value: number, offset: number, noAssert?: boolean): number; + writeDoubleLE(value: number, offset: number, noAssert?: boolean): number; + writeDoubleBE(value: number, offset: number, noAssert?: boolean): number; + fill(value: any, offset?: number, end?: number): this; + indexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number; + lastIndexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number; + includes(value: string | number | Buffer, byteOffset?: number, encoding?: string): boolean; + + /** + * Allocates a new buffer containing the given {str}. + * + * @param str String to store in buffer. + * @param encoding encoding to use, optional. Default is 'utf8' + */ + constructor (str: string, encoding?: string); + /** + * Allocates a new buffer of {size} octets. + * + * @param size count of octets to allocate. + */ + constructor (size: number); + /** + * Allocates a new buffer containing the given {array} of octets. + * + * @param array The octets to store. + */ + constructor (array: Uint8Array); + /** + * Produces a Buffer backed by the same allocated memory as + * the given {ArrayBuffer}. + * + * + * @param arrayBuffer The ArrayBuffer with which to share memory. + */ + constructor (arrayBuffer: ArrayBuffer); + /** + * Allocates a new buffer containing the given {array} of octets. + * + * @param array The octets to store. + */ + constructor (array: any[]); + /** + * Copies the passed {buffer} data onto a new {Buffer} instance. + * + * @param buffer The buffer to copy. + */ + constructor (buffer: Buffer); + prototype: Buffer; + /** + * Allocates a new Buffer using an {array} of octets. + * + * @param array + */ + static from(array: any[]): Buffer; + /** + * When passed a reference to the .buffer property of a TypedArray instance, + * the newly created Buffer will share the same allocated memory as the TypedArray. + * The optional {byteOffset} and {length} arguments specify a memory range + * within the {arrayBuffer} that will be shared by the Buffer. + * + * @param arrayBuffer The .buffer property of a TypedArray or a new ArrayBuffer() + * @param byteOffset + * @param length + */ + static from(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer; + /** + * Copies the passed {buffer} data onto a new Buffer instance. + * + * @param buffer + */ + static from(buffer: Buffer): Buffer; + /** + * Creates a new Buffer containing the given JavaScript string {str}. + * If provided, the {encoding} parameter identifies the character encoding. + * If not provided, {encoding} defaults to 'utf8'. + * + * @param str + */ + static from(str: string, encoding?: string): Buffer; + /** + * Returns true if {obj} is a Buffer + * + * @param obj object to test. + */ + static isBuffer(obj: any): obj is Buffer; + /** + * Returns true if {encoding} is a valid encoding argument. + * Valid string encodings in Node 0.12: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex' + * + * @param encoding string to test. + */ + static isEncoding(encoding: string): boolean; + /** + * Gives the actual byte length of a string. encoding defaults to 'utf8'. + * This is not the same as String.prototype.length since that returns the number of characters in a string. + * + * @param string string to test. + * @param encoding encoding used to evaluate (defaults to 'utf8') + */ + static byteLength(string: string, encoding?: string): number; + /** + * Returns a buffer which is the result of concatenating all the buffers in the list together. + * + * If the list has no items, or if the totalLength is 0, then it returns a zero-length buffer. + * If the list has exactly one item, then the first item of the list is returned. + * If the list has more than one item, then a new Buffer is created. + * + * @param list An array of Buffer objects to concatenate + * @param totalLength Total length of the buffers when concatenated. + * If totalLength is not provided, it is read from the buffers in the list. However, this adds an additional loop to the function, so it is faster to provide the length explicitly. + */ + static concat(list: Buffer[], totalLength?: number): Buffer; + /** + * The same as buf1.compare(buf2). + */ + static compare(buf1: Buffer, buf2: Buffer): number; + /** + * Allocates a new buffer of {size} octets. + * + * @param size count of octets to allocate. + * @param fill if specified, buffer will be initialized by calling buf.fill(fill). + * If parameter is omitted, buffer will be filled with zeros. + * @param encoding encoding used for call to buf.fill while initalizing + */ + static alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer; + /** + * Allocates a new buffer of {size} octets, leaving memory not initialized, so the contents + * of the newly created Buffer are unknown and may contain sensitive data. + * + * @param size count of octets to allocate + */ + static allocUnsafe(size: number): Buffer; + /** + * Allocates a new non-pooled buffer of {size} octets, leaving memory not initialized, so the contents + * of the newly created Buffer are unknown and may contain sensitive data. + * + * @param size count of octets to allocate + */ + static allocUnsafeSlow(size: number): Buffer; + } +} \ No newline at end of file diff --git a/node_modules/safe-buffer/index.js b/node_modules/safe-buffer/index.js new file mode 100644 index 0000000..f8d3ec9 --- /dev/null +++ b/node_modules/safe-buffer/index.js @@ -0,0 +1,65 @@ +/*! safe-buffer. MIT License. Feross Aboukhadijeh */ +/* eslint-disable node/no-deprecated-api */ +var buffer = require('buffer') +var Buffer = buffer.Buffer + +// alternative to using Object.keys for old browsers +function copyProps (src, dst) { + for (var key in src) { + dst[key] = src[key] + } +} +if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { + module.exports = buffer +} else { + // Copy properties from require('buffer') + copyProps(buffer, exports) + exports.Buffer = SafeBuffer +} + +function SafeBuffer (arg, encodingOrOffset, length) { + return Buffer(arg, encodingOrOffset, length) +} + +SafeBuffer.prototype = Object.create(Buffer.prototype) + +// Copy static methods from Buffer +copyProps(Buffer, SafeBuffer) + +SafeBuffer.from = function (arg, encodingOrOffset, length) { + if (typeof arg === 'number') { + throw new TypeError('Argument must not be a number') + } + return Buffer(arg, encodingOrOffset, length) +} + +SafeBuffer.alloc = function (size, fill, encoding) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + var buf = Buffer(size) + if (fill !== undefined) { + if (typeof encoding === 'string') { + buf.fill(fill, encoding) + } else { + buf.fill(fill) + } + } else { + buf.fill(0) + } + return buf +} + +SafeBuffer.allocUnsafe = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return Buffer(size) +} + +SafeBuffer.allocUnsafeSlow = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return buffer.SlowBuffer(size) +} diff --git a/node_modules/safe-buffer/package.json b/node_modules/safe-buffer/package.json new file mode 100644 index 0000000..f374112 --- /dev/null +++ b/node_modules/safe-buffer/package.json @@ -0,0 +1,78 @@ +{ + "_from": "safe-buffer@^5.0.1", + "_id": "safe-buffer@5.2.1", + "_inBundle": false, + "_integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "_location": "/safe-buffer", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "safe-buffer@^5.0.1", + "name": "safe-buffer", + "escapedName": "safe-buffer", + "rawSpec": "^5.0.1", + "saveSpec": null, + "fetchSpec": "^5.0.1" + }, + "_requiredBy": [ + "/ecdsa-sig-formatter", + "/jwa", + "/jws" + ], + "_resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "_shasum": "1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6", + "_spec": "safe-buffer@^5.0.1", + "_where": "D:\\Users\\user\\Documents\\Portofolio\\Github\\WebsiteFootballPWA\\node_modules\\jws", + "author": { + "name": "Feross Aboukhadijeh", + "email": "feross@feross.org", + "url": "https://feross.org" + }, + "bugs": { + "url": "https://github.com/feross/safe-buffer/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Safer Node.js Buffer API", + "devDependencies": { + "standard": "*", + "tape": "^5.0.0" + }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "homepage": "https://github.com/feross/safe-buffer", + "keywords": [ + "buffer", + "buffer allocate", + "node security", + "safe", + "safe-buffer", + "security", + "uninitialized" + ], + "license": "MIT", + "main": "index.js", + "name": "safe-buffer", + "repository": { + "type": "git", + "url": "git://github.com/feross/safe-buffer.git" + }, + "scripts": { + "test": "standard && tape test/*.js" + }, + "types": "index.d.ts", + "version": "5.2.1" +} diff --git a/node_modules/safer-buffer/LICENSE b/node_modules/safer-buffer/LICENSE new file mode 100644 index 0000000..4fe9e6f --- /dev/null +++ b/node_modules/safer-buffer/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Nikita Skovoroda + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/safer-buffer/Porting-Buffer.md b/node_modules/safer-buffer/Porting-Buffer.md new file mode 100644 index 0000000..68d86ba --- /dev/null +++ b/node_modules/safer-buffer/Porting-Buffer.md @@ -0,0 +1,268 @@ +# Porting to the Buffer.from/Buffer.alloc API + + +## Overview + +- [Variant 1: Drop support for Node.js ≤ 4.4.x and 5.0.0 — 5.9.x.](#variant-1) (*recommended*) +- [Variant 2: Use a polyfill](#variant-2) +- [Variant 3: manual detection, with safeguards](#variant-3) + +### Finding problematic bits of code using grep + +Just run `grep -nrE '[^a-zA-Z](Slow)?Buffer\s*\(' --exclude-dir node_modules`. + +It will find all the potentially unsafe places in your own code (with some considerably unlikely +exceptions). + +### Finding problematic bits of code using Node.js 8 + +If you’re using Node.js ≥ 8.0.0 (which is recommended), Node.js exposes multiple options that help with finding the relevant pieces of code: + +- `--trace-warnings` will make Node.js show a stack trace for this warning and other warnings that are printed by Node.js. +- `--trace-deprecation` does the same thing, but only for deprecation warnings. +- `--pending-deprecation` will show more types of deprecation warnings. In particular, it will show the `Buffer()` deprecation warning, even on Node.js 8. + +You can set these flags using an environment variable: + +```console +$ export NODE_OPTIONS='--trace-warnings --pending-deprecation' +$ cat example.js +'use strict'; +const foo = new Buffer('foo'); +$ node example.js +(node:7147) [DEP0005] DeprecationWarning: The Buffer() and new Buffer() constructors are not recommended for use due to security and usability concerns. Please use the new Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() construction methods instead. + at showFlaggedDeprecation (buffer.js:127:13) + at new Buffer (buffer.js:148:3) + at Object. (/path/to/example.js:2:13) + [... more stack trace lines ...] +``` + +### Finding problematic bits of code using linters + +Eslint rules [no-buffer-constructor](https://eslint.org/docs/rules/no-buffer-constructor) +or +[node/no-deprecated-api](https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/no-deprecated-api.md) +also find calls to deprecated `Buffer()` API. Those rules are included in some pre-sets. + +There is a drawback, though, that it doesn't always +[work correctly](https://github.com/chalker/safer-buffer#why-not-safe-buffer) when `Buffer` is +overriden e.g. with a polyfill, so recommended is a combination of this and some other method +described above. + + +## Variant 1: Drop support for Node.js ≤ 4.4.x and 5.0.0 — 5.9.x. + +This is the recommended solution nowadays that would imply only minimal overhead. + +The Node.js 5.x release line has been unsupported since July 2016, and the Node.js 4.x release line reaches its End of Life in April 2018 (→ [Schedule](https://github.com/nodejs/Release#release-schedule)). This means that these versions of Node.js will *not* receive any updates, even in case of security issues, so using these release lines should be avoided, if at all possible. + +What you would do in this case is to convert all `new Buffer()` or `Buffer()` calls to use `Buffer.alloc()` or `Buffer.from()`, in the following way: + +- For `new Buffer(number)`, replace it with `Buffer.alloc(number)`. +- For `new Buffer(string)` (or `new Buffer(string, encoding)`), replace it with `Buffer.from(string)` (or `Buffer.from(string, encoding)`). +- For all other combinations of arguments (these are much rarer), also replace `new Buffer(...arguments)` with `Buffer.from(...arguments)`. + +Note that `Buffer.alloc()` is also _faster_ on the current Node.js versions than +`new Buffer(size).fill(0)`, which is what you would otherwise need to ensure zero-filling. + +Enabling eslint rule [no-buffer-constructor](https://eslint.org/docs/rules/no-buffer-constructor) +or +[node/no-deprecated-api](https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/no-deprecated-api.md) +is recommended to avoid accidential unsafe Buffer API usage. + +There is also a [JSCodeshift codemod](https://github.com/joyeecheung/node-dep-codemod#dep005) +for automatically migrating Buffer constructors to `Buffer.alloc()` or `Buffer.from()`. +Note that it currently only works with cases where the arguments are literals or where the +constructor is invoked with two arguments. + +_If you currently support those older Node.js versions and dropping them would be a semver-major change +for you, or if you support older branches of your packages, consider using [Variant 2](#variant-2) +or [Variant 3](#variant-3) on older branches, so people using those older branches will also receive +the fix. That way, you will eradicate potential issues caused by unguarded Buffer API usage and +your users will not observe a runtime deprecation warning when running your code on Node.js 10._ + + +## Variant 2: Use a polyfill + +Utilize [safer-buffer](https://www.npmjs.com/package/safer-buffer) as a polyfill to support older +Node.js versions. + +You would take exacly the same steps as in [Variant 1](#variant-1), but with a polyfill +`const Buffer = require('safer-buffer').Buffer` in all files where you use the new `Buffer` api. + +Make sure that you do not use old `new Buffer` API — in any files where the line above is added, +using old `new Buffer()` API will _throw_. It will be easy to notice that in CI, though. + +Alternatively, you could use [buffer-from](https://www.npmjs.com/package/buffer-from) and/or +[buffer-alloc](https://www.npmjs.com/package/buffer-alloc) [ponyfills](https://ponyfill.com/) — +those are great, the only downsides being 4 deps in the tree and slightly more code changes to +migrate off them (as you would be using e.g. `Buffer.from` under a different name). If you need only +`Buffer.from` polyfilled — `buffer-from` alone which comes with no extra dependencies. + +_Alternatively, you could use [safe-buffer](https://www.npmjs.com/package/safe-buffer) — it also +provides a polyfill, but takes a different approach which has +[it's drawbacks](https://github.com/chalker/safer-buffer#why-not-safe-buffer). It will allow you +to also use the older `new Buffer()` API in your code, though — but that's arguably a benefit, as +it is problematic, can cause issues in your code, and will start emitting runtime deprecation +warnings starting with Node.js 10._ + +Note that in either case, it is important that you also remove all calls to the old Buffer +API manually — just throwing in `safe-buffer` doesn't fix the problem by itself, it just provides +a polyfill for the new API. I have seen people doing that mistake. + +Enabling eslint rule [no-buffer-constructor](https://eslint.org/docs/rules/no-buffer-constructor) +or +[node/no-deprecated-api](https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/no-deprecated-api.md) +is recommended. + +_Don't forget to drop the polyfill usage once you drop support for Node.js < 4.5.0._ + + +## Variant 3 — manual detection, with safeguards + +This is useful if you create Buffer instances in only a few places (e.g. one), or you have your own +wrapper around them. + +### Buffer(0) + +This special case for creating empty buffers can be safely replaced with `Buffer.concat([])`, which +returns the same result all the way down to Node.js 0.8.x. + +### Buffer(notNumber) + +Before: + +```js +var buf = new Buffer(notNumber, encoding); +``` + +After: + +```js +var buf; +if (Buffer.from && Buffer.from !== Uint8Array.from) { + buf = Buffer.from(notNumber, encoding); +} else { + if (typeof notNumber === 'number') + throw new Error('The "size" argument must be of type number.'); + buf = new Buffer(notNumber, encoding); +} +``` + +`encoding` is optional. + +Note that the `typeof notNumber` before `new Buffer` is required (for cases when `notNumber` argument is not +hard-coded) and _is not caused by the deprecation of Buffer constructor_ — it's exactly _why_ the +Buffer constructor is deprecated. Ecosystem packages lacking this type-check caused numereous +security issues — situations when unsanitized user input could end up in the `Buffer(arg)` create +problems ranging from DoS to leaking sensitive information to the attacker from the process memory. + +When `notNumber` argument is hardcoded (e.g. literal `"abc"` or `[0,1,2]`), the `typeof` check can +be omitted. + +Also note that using TypeScript does not fix this problem for you — when libs written in +`TypeScript` are used from JS, or when user input ends up there — it behaves exactly as pure JS, as +all type checks are translation-time only and are not present in the actual JS code which TS +compiles to. + +### Buffer(number) + +For Node.js 0.10.x (and below) support: + +```js +var buf; +if (Buffer.alloc) { + buf = Buffer.alloc(number); +} else { + buf = new Buffer(number); + buf.fill(0); +} +``` + +Otherwise (Node.js ≥ 0.12.x): + +```js +const buf = Buffer.alloc ? Buffer.alloc(number) : new Buffer(number).fill(0); +``` + +## Regarding Buffer.allocUnsafe + +Be extra cautious when using `Buffer.allocUnsafe`: + * Don't use it if you don't have a good reason to + * e.g. you probably won't ever see a performance difference for small buffers, in fact, those + might be even faster with `Buffer.alloc()`, + * if your code is not in the hot code path — you also probably won't notice a difference, + * keep in mind that zero-filling minimizes the potential risks. + * If you use it, make sure that you never return the buffer in a partially-filled state, + * if you are writing to it sequentially — always truncate it to the actuall written length + +Errors in handling buffers allocated with `Buffer.allocUnsafe` could result in various issues, +ranged from undefined behaviour of your code to sensitive data (user input, passwords, certs) +leaking to the remote attacker. + +_Note that the same applies to `new Buffer` usage without zero-filling, depending on the Node.js +version (and lacking type checks also adds DoS to the list of potential problems)._ + + +## FAQ + + +### What is wrong with the `Buffer` constructor? + +The `Buffer` constructor could be used to create a buffer in many different ways: + +- `new Buffer(42)` creates a `Buffer` of 42 bytes. Before Node.js 8, this buffer contained + *arbitrary memory* for performance reasons, which could include anything ranging from + program source code to passwords and encryption keys. +- `new Buffer('abc')` creates a `Buffer` that contains the UTF-8-encoded version of + the string `'abc'`. A second argument could specify another encoding: For example, + `new Buffer(string, 'base64')` could be used to convert a Base64 string into the original + sequence of bytes that it represents. +- There are several other combinations of arguments. + +This meant that, in code like `var buffer = new Buffer(foo);`, *it is not possible to tell +what exactly the contents of the generated buffer are* without knowing the type of `foo`. + +Sometimes, the value of `foo` comes from an external source. For example, this function +could be exposed as a service on a web server, converting a UTF-8 string into its Base64 form: + +``` +function stringToBase64(req, res) { + // The request body should have the format of `{ string: 'foobar' }` + const rawBytes = new Buffer(req.body.string) + const encoded = rawBytes.toString('base64') + res.end({ encoded: encoded }) +} +``` + +Note that this code does *not* validate the type of `req.body.string`: + +- `req.body.string` is expected to be a string. If this is the case, all goes well. +- `req.body.string` is controlled by the client that sends the request. +- If `req.body.string` is the *number* `50`, the `rawBytes` would be 50 bytes: + - Before Node.js 8, the content would be uninitialized + - After Node.js 8, the content would be `50` bytes with the value `0` + +Because of the missing type check, an attacker could intentionally send a number +as part of the request. Using this, they can either: + +- Read uninitialized memory. This **will** leak passwords, encryption keys and other + kinds of sensitive information. (Information leak) +- Force the program to allocate a large amount of memory. For example, when specifying + `500000000` as the input value, each request will allocate 500MB of memory. + This can be used to either exhaust the memory available of a program completely + and make it crash, or slow it down significantly. (Denial of Service) + +Both of these scenarios are considered serious security issues in a real-world +web server context. + +when using `Buffer.from(req.body.string)` instead, passing a number will always +throw an exception instead, giving a controlled behaviour that can always be +handled by the program. + + +### The `Buffer()` constructor has been deprecated for a while. Is this really an issue? + +Surveys of code in the `npm` ecosystem have shown that the `Buffer()` constructor is still +widely used. This includes new code, and overall usage of such code has actually been +*increasing*. diff --git a/node_modules/safer-buffer/Readme.md b/node_modules/safer-buffer/Readme.md new file mode 100644 index 0000000..14b0822 --- /dev/null +++ b/node_modules/safer-buffer/Readme.md @@ -0,0 +1,156 @@ +# safer-buffer [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![javascript style guide][standard-image]][standard-url] [![Security Responsible Disclosure][secuirty-image]][secuirty-url] + +[travis-image]: https://travis-ci.org/ChALkeR/safer-buffer.svg?branch=master +[travis-url]: https://travis-ci.org/ChALkeR/safer-buffer +[npm-image]: https://img.shields.io/npm/v/safer-buffer.svg +[npm-url]: https://npmjs.org/package/safer-buffer +[standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg +[standard-url]: https://standardjs.com +[secuirty-image]: https://img.shields.io/badge/Security-Responsible%20Disclosure-green.svg +[secuirty-url]: https://github.com/nodejs/security-wg/blob/master/processes/responsible_disclosure_template.md + +Modern Buffer API polyfill without footguns, working on Node.js from 0.8 to current. + +## How to use? + +First, port all `Buffer()` and `new Buffer()` calls to `Buffer.alloc()` and `Buffer.from()` API. + +Then, to achieve compatibility with outdated Node.js versions (`<4.5.0` and 5.x `<5.9.0`), use +`const Buffer = require('safer-buffer').Buffer` in all files where you make calls to the new +Buffer API. _Use `var` instead of `const` if you need that for your Node.js version range support._ + +Also, see the +[porting Buffer](https://github.com/ChALkeR/safer-buffer/blob/master/Porting-Buffer.md) guide. + +## Do I need it? + +Hopefully, not — dropping support for outdated Node.js versions should be fine nowdays, and that +is the recommended path forward. You _do_ need to port to the `Buffer.alloc()` and `Buffer.from()` +though. + +See the [porting guide](https://github.com/ChALkeR/safer-buffer/blob/master/Porting-Buffer.md) +for a better description. + +## Why not [safe-buffer](https://npmjs.com/safe-buffer)? + +_In short: while `safe-buffer` serves as a polyfill for the new API, it allows old API usage and +itself contains footguns._ + +`safe-buffer` could be used safely to get the new API while still keeping support for older +Node.js versions (like this module), but while analyzing ecosystem usage of the old Buffer API +I found out that `safe-buffer` is itself causing problems in some cases. + +For example, consider the following snippet: + +```console +$ cat example.unsafe.js +console.log(Buffer(20)) +$ ./node-v6.13.0-linux-x64/bin/node example.unsafe.js + +$ standard example.unsafe.js +standard: Use JavaScript Standard Style (https://standardjs.com) + /home/chalker/repo/safer-buffer/example.unsafe.js:2:13: 'Buffer()' was deprecated since v6. Use 'Buffer.alloc()' or 'Buffer.from()' (use 'https://www.npmjs.com/package/safe-buffer' for '<4.5.0') instead. +``` + +This is allocates and writes to console an uninitialized chunk of memory. +[standard](https://www.npmjs.com/package/standard) linter (among others) catch that and warn people +to avoid using unsafe API. + +Let's now throw in `safe-buffer`! + +```console +$ cat example.safe-buffer.js +const Buffer = require('safe-buffer').Buffer +console.log(Buffer(20)) +$ standard example.safe-buffer.js +$ ./node-v6.13.0-linux-x64/bin/node example.safe-buffer.js + +``` + +See the problem? Adding in `safe-buffer` _magically removes the lint warning_, but the behavior +remains identiсal to what we had before, and when launched on Node.js 6.x LTS — this dumps out +chunks of uninitialized memory. +_And this code will still emit runtime warnings on Node.js 10.x and above._ + +That was done by design. I first considered changing `safe-buffer`, prohibiting old API usage or +emitting warnings on it, but that significantly diverges from `safe-buffer` design. After some +discussion, it was decided to move my approach into a separate package, and _this is that separate +package_. + +This footgun is not imaginary — I observed top-downloaded packages doing that kind of thing, +«fixing» the lint warning by blindly including `safe-buffer` without any actual changes. + +Also in some cases, even if the API _was_ migrated to use of safe Buffer API — a random pull request +can bring unsafe Buffer API usage back to the codebase by adding new calls — and that could go +unnoticed even if you have a linter prohibiting that (becase of the reason stated above), and even +pass CI. _I also observed that being done in popular packages._ + +Some examples: + * [webdriverio](https://github.com/webdriverio/webdriverio/commit/05cbd3167c12e4930f09ef7cf93b127ba4effae4#diff-124380949022817b90b622871837d56cR31) + (a module with 548 759 downloads/month), + * [websocket-stream](https://github.com/maxogden/websocket-stream/commit/c9312bd24d08271687d76da0fe3c83493871cf61) + (218 288 d/m, fix in [maxogden/websocket-stream#142](https://github.com/maxogden/websocket-stream/pull/142)), + * [node-serialport](https://github.com/node-serialport/node-serialport/commit/e8d9d2b16c664224920ce1c895199b1ce2def48c) + (113 138 d/m, fix in [node-serialport/node-serialport#1510](https://github.com/node-serialport/node-serialport/pull/1510)), + * [karma](https://github.com/karma-runner/karma/commit/3d94b8cf18c695104ca195334dc75ff054c74eec) + (3 973 193 d/m, fix in [karma-runner/karma#2947](https://github.com/karma-runner/karma/pull/2947)), + * [spdy-transport](https://github.com/spdy-http2/spdy-transport/commit/5375ac33f4a62a4f65bcfc2827447d42a5dbe8b1) + (5 970 727 d/m, fix in [spdy-http2/spdy-transport#53](https://github.com/spdy-http2/spdy-transport/pull/53)). + * And there are a lot more over the ecosystem. + +I filed a PR at +[mysticatea/eslint-plugin-node#110](https://github.com/mysticatea/eslint-plugin-node/pull/110) to +partially fix that (for cases when that lint rule is used), but it is a semver-major change for +linter rules and presets, so it would take significant time for that to reach actual setups. +_It also hasn't been released yet (2018-03-20)._ + +Also, `safer-buffer` discourages the usage of `.allocUnsafe()`, which is often done by a mistake. +It still supports it with an explicit concern barier, by placing it under +`require('safer-buffer/dangereous')`. + +## But isn't throwing bad? + +Not really. It's an error that could be noticed and fixed early, instead of causing havoc later like +unguarded `new Buffer()` calls that end up receiving user input can do. + +This package affects only the files where `var Buffer = require('safer-buffer').Buffer` was done, so +it is really simple to keep track of things and make sure that you don't mix old API usage with that. +Also, CI should hint anything that you might have missed. + +New commits, if tested, won't land new usage of unsafe Buffer API this way. +_Node.js 10.x also deals with that by printing a runtime depecation warning._ + +### Would it affect third-party modules? + +No, unless you explicitly do an awful thing like monkey-patching or overriding the built-in `Buffer`. +Don't do that. + +### But I don't want throwing… + +That is also fine! + +Also, it could be better in some cases when you don't comprehensive enough test coverage. + +In that case — just don't override `Buffer` and use +`var SaferBuffer = require('safer-buffer').Buffer` instead. + +That way, everything using `Buffer` natively would still work, but there would be two drawbacks: + +* `Buffer.from`/`Buffer.alloc` won't be polyfilled — use `SaferBuffer.from` and + `SaferBuffer.alloc` instead. +* You are still open to accidentally using the insecure deprecated API — use a linter to catch that. + +Note that using a linter to catch accidential `Buffer` constructor usage in this case is strongly +recommended. `Buffer` is not overriden in this usecase, so linters won't get confused. + +## «Without footguns»? + +Well, it is still possible to do _some_ things with `Buffer` API, e.g. accessing `.buffer` property +on older versions and duping things from there. You shouldn't do that in your code, probabably. + +The intention is to remove the most significant footguns that affect lots of packages in the +ecosystem, and to do it in the proper way. + +Also, this package doesn't protect against security issues affecting some Node.js versions, so for +usage in your own production code, it is still recommended to update to a Node.js version +[supported by upstream](https://github.com/nodejs/release#release-schedule). diff --git a/node_modules/safer-buffer/dangerous.js b/node_modules/safer-buffer/dangerous.js new file mode 100644 index 0000000..ca41fdc --- /dev/null +++ b/node_modules/safer-buffer/dangerous.js @@ -0,0 +1,58 @@ +/* eslint-disable node/no-deprecated-api */ + +'use strict' + +var buffer = require('buffer') +var Buffer = buffer.Buffer +var safer = require('./safer.js') +var Safer = safer.Buffer + +var dangerous = {} + +var key + +for (key in safer) { + if (!safer.hasOwnProperty(key)) continue + dangerous[key] = safer[key] +} + +var Dangereous = dangerous.Buffer = {} + +// Copy Safer API +for (key in Safer) { + if (!Safer.hasOwnProperty(key)) continue + Dangereous[key] = Safer[key] +} + +// Copy those missing unsafe methods, if they are present +for (key in Buffer) { + if (!Buffer.hasOwnProperty(key)) continue + if (Dangereous.hasOwnProperty(key)) continue + Dangereous[key] = Buffer[key] +} + +if (!Dangereous.allocUnsafe) { + Dangereous.allocUnsafe = function (size) { + if (typeof size !== 'number') { + throw new TypeError('The "size" argument must be of type number. Received type ' + typeof size) + } + if (size < 0 || size >= 2 * (1 << 30)) { + throw new RangeError('The value "' + size + '" is invalid for option "size"') + } + return Buffer(size) + } +} + +if (!Dangereous.allocUnsafeSlow) { + Dangereous.allocUnsafeSlow = function (size) { + if (typeof size !== 'number') { + throw new TypeError('The "size" argument must be of type number. Received type ' + typeof size) + } + if (size < 0 || size >= 2 * (1 << 30)) { + throw new RangeError('The value "' + size + '" is invalid for option "size"') + } + return buffer.SlowBuffer(size) + } +} + +module.exports = dangerous diff --git a/node_modules/safer-buffer/package.json b/node_modules/safer-buffer/package.json new file mode 100644 index 0000000..37c4280 --- /dev/null +++ b/node_modules/safer-buffer/package.json @@ -0,0 +1,60 @@ +{ + "_from": "safer-buffer@^2.1.0", + "_id": "safer-buffer@2.1.2", + "_inBundle": false, + "_integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "_location": "/safer-buffer", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "safer-buffer@^2.1.0", + "name": "safer-buffer", + "escapedName": "safer-buffer", + "rawSpec": "^2.1.0", + "saveSpec": null, + "fetchSpec": "^2.1.0" + }, + "_requiredBy": [ + "/asn1.js" + ], + "_resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "_shasum": "44fa161b0187b9549dd84bb91802f9bd8385cd6a", + "_spec": "safer-buffer@^2.1.0", + "_where": "D:\\Users\\user\\Documents\\Portofolio\\Github\\WebsiteFootballPWA\\node_modules\\asn1.js", + "author": { + "name": "Nikita Skovoroda", + "email": "chalkerx@gmail.com", + "url": "https://github.com/ChALkeR" + }, + "bugs": { + "url": "https://github.com/ChALkeR/safer-buffer/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Modern Buffer API polyfill without footguns", + "devDependencies": { + "standard": "^11.0.1", + "tape": "^4.9.0" + }, + "files": [ + "Porting-Buffer.md", + "Readme.md", + "tests.js", + "dangerous.js", + "safer.js" + ], + "homepage": "https://github.com/ChALkeR/safer-buffer#readme", + "license": "MIT", + "main": "safer.js", + "name": "safer-buffer", + "repository": { + "type": "git", + "url": "git+https://github.com/ChALkeR/safer-buffer.git" + }, + "scripts": { + "browserify-test": "browserify --external tape tests.js > browserify-tests.js && tape browserify-tests.js", + "test": "standard && tape tests.js" + }, + "version": "2.1.2" +} diff --git a/node_modules/safer-buffer/safer.js b/node_modules/safer-buffer/safer.js new file mode 100644 index 0000000..37c7e1a --- /dev/null +++ b/node_modules/safer-buffer/safer.js @@ -0,0 +1,77 @@ +/* eslint-disable node/no-deprecated-api */ + +'use strict' + +var buffer = require('buffer') +var Buffer = buffer.Buffer + +var safer = {} + +var key + +for (key in buffer) { + if (!buffer.hasOwnProperty(key)) continue + if (key === 'SlowBuffer' || key === 'Buffer') continue + safer[key] = buffer[key] +} + +var Safer = safer.Buffer = {} +for (key in Buffer) { + if (!Buffer.hasOwnProperty(key)) continue + if (key === 'allocUnsafe' || key === 'allocUnsafeSlow') continue + Safer[key] = Buffer[key] +} + +safer.Buffer.prototype = Buffer.prototype + +if (!Safer.from || Safer.from === Uint8Array.from) { + Safer.from = function (value, encodingOrOffset, length) { + if (typeof value === 'number') { + throw new TypeError('The "value" argument must not be of type number. Received type ' + typeof value) + } + if (value && typeof value.length === 'undefined') { + throw new TypeError('The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type ' + typeof value) + } + return Buffer(value, encodingOrOffset, length) + } +} + +if (!Safer.alloc) { + Safer.alloc = function (size, fill, encoding) { + if (typeof size !== 'number') { + throw new TypeError('The "size" argument must be of type number. Received type ' + typeof size) + } + if (size < 0 || size >= 2 * (1 << 30)) { + throw new RangeError('The value "' + size + '" is invalid for option "size"') + } + var buf = Buffer(size) + if (!fill || fill.length === 0) { + buf.fill(0) + } else if (typeof encoding === 'string') { + buf.fill(fill, encoding) + } else { + buf.fill(fill) + } + return buf + } +} + +if (!safer.kStringMaxLength) { + try { + safer.kStringMaxLength = process.binding('buffer').kStringMaxLength + } catch (e) { + // we can't determine kStringMaxLength in environments where process.binding + // is unsupported, so let's not set it + } +} + +if (!safer.constants) { + safer.constants = { + MAX_LENGTH: safer.kMaxLength + } + if (safer.kStringMaxLength) { + safer.constants.MAX_STRING_LENGTH = safer.kStringMaxLength + } +} + +module.exports = safer diff --git a/node_modules/safer-buffer/tests.js b/node_modules/safer-buffer/tests.js new file mode 100644 index 0000000..7ed2777 --- /dev/null +++ b/node_modules/safer-buffer/tests.js @@ -0,0 +1,406 @@ +/* eslint-disable node/no-deprecated-api */ + +'use strict' + +var test = require('tape') + +var buffer = require('buffer') + +var index = require('./') +var safer = require('./safer') +var dangerous = require('./dangerous') + +/* Inheritance tests */ + +test('Default is Safer', function (t) { + t.equal(index, safer) + t.notEqual(safer, dangerous) + t.notEqual(index, dangerous) + t.end() +}) + +test('Is not a function', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(typeof impl, 'object') + t.equal(typeof impl.Buffer, 'object') + }); + [buffer].forEach(function (impl) { + t.equal(typeof impl, 'object') + t.equal(typeof impl.Buffer, 'function') + }) + t.end() +}) + +test('Constructor throws', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.throws(function () { impl.Buffer() }) + t.throws(function () { impl.Buffer(0) }) + t.throws(function () { impl.Buffer('a') }) + t.throws(function () { impl.Buffer('a', 'utf-8') }) + t.throws(function () { return new impl.Buffer() }) + t.throws(function () { return new impl.Buffer(0) }) + t.throws(function () { return new impl.Buffer('a') }) + t.throws(function () { return new impl.Buffer('a', 'utf-8') }) + }) + t.end() +}) + +test('Safe methods exist', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(typeof impl.Buffer.alloc, 'function', 'alloc') + t.equal(typeof impl.Buffer.from, 'function', 'from') + }) + t.end() +}) + +test('Unsafe methods exist only in Dangerous', function (t) { + [index, safer].forEach(function (impl) { + t.equal(typeof impl.Buffer.allocUnsafe, 'undefined') + t.equal(typeof impl.Buffer.allocUnsafeSlow, 'undefined') + }); + [dangerous].forEach(function (impl) { + t.equal(typeof impl.Buffer.allocUnsafe, 'function') + t.equal(typeof impl.Buffer.allocUnsafeSlow, 'function') + }) + t.end() +}) + +test('Generic methods/properties are defined and equal', function (t) { + ['poolSize', 'isBuffer', 'concat', 'byteLength'].forEach(function (method) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer[method], buffer.Buffer[method], method) + t.notEqual(typeof impl.Buffer[method], 'undefined', method) + }) + }) + t.end() +}) + +test('Built-in buffer static methods/properties are inherited', function (t) { + Object.keys(buffer).forEach(function (method) { + if (method === 'SlowBuffer' || method === 'Buffer') return; + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl[method], buffer[method], method) + t.notEqual(typeof impl[method], 'undefined', method) + }) + }) + t.end() +}) + +test('Built-in Buffer static methods/properties are inherited', function (t) { + Object.keys(buffer.Buffer).forEach(function (method) { + if (method === 'allocUnsafe' || method === 'allocUnsafeSlow') return; + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer[method], buffer.Buffer[method], method) + t.notEqual(typeof impl.Buffer[method], 'undefined', method) + }) + }) + t.end() +}) + +test('.prototype property of Buffer is inherited', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer.prototype, buffer.Buffer.prototype, 'prototype') + t.notEqual(typeof impl.Buffer.prototype, 'undefined', 'prototype') + }) + t.end() +}) + +test('All Safer methods are present in Dangerous', function (t) { + Object.keys(safer).forEach(function (method) { + if (method === 'Buffer') return; + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl[method], safer[method], method) + if (method !== 'kStringMaxLength') { + t.notEqual(typeof impl[method], 'undefined', method) + } + }) + }) + Object.keys(safer.Buffer).forEach(function (method) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer[method], safer.Buffer[method], method) + t.notEqual(typeof impl.Buffer[method], 'undefined', method) + }) + }) + t.end() +}) + +test('Safe methods from Dangerous methods are present in Safer', function (t) { + Object.keys(dangerous).forEach(function (method) { + if (method === 'Buffer') return; + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl[method], dangerous[method], method) + if (method !== 'kStringMaxLength') { + t.notEqual(typeof impl[method], 'undefined', method) + } + }) + }) + Object.keys(dangerous.Buffer).forEach(function (method) { + if (method === 'allocUnsafe' || method === 'allocUnsafeSlow') return; + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer[method], dangerous.Buffer[method], method) + t.notEqual(typeof impl.Buffer[method], 'undefined', method) + }) + }) + t.end() +}) + +/* Behaviour tests */ + +test('Methods return Buffers', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(0))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(0, 10))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(0, 'a'))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(10))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(10, 'x'))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(9, 'ab'))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from(''))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from('string'))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from('string', 'utf-8'))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from('b25ldHdvdGhyZWU=', 'base64'))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from([0, 42, 3]))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from(new Uint8Array([0, 42, 3])))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from([]))) + }); + ['allocUnsafe', 'allocUnsafeSlow'].forEach(function (method) { + t.ok(buffer.Buffer.isBuffer(dangerous.Buffer[method](0))) + t.ok(buffer.Buffer.isBuffer(dangerous.Buffer[method](10))) + }) + t.end() +}) + +test('Constructor is buffer.Buffer', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer.alloc(0).constructor, buffer.Buffer) + t.equal(impl.Buffer.alloc(0, 10).constructor, buffer.Buffer) + t.equal(impl.Buffer.alloc(0, 'a').constructor, buffer.Buffer) + t.equal(impl.Buffer.alloc(10).constructor, buffer.Buffer) + t.equal(impl.Buffer.alloc(10, 'x').constructor, buffer.Buffer) + t.equal(impl.Buffer.alloc(9, 'ab').constructor, buffer.Buffer) + t.equal(impl.Buffer.from('').constructor, buffer.Buffer) + t.equal(impl.Buffer.from('string').constructor, buffer.Buffer) + t.equal(impl.Buffer.from('string', 'utf-8').constructor, buffer.Buffer) + t.equal(impl.Buffer.from('b25ldHdvdGhyZWU=', 'base64').constructor, buffer.Buffer) + t.equal(impl.Buffer.from([0, 42, 3]).constructor, buffer.Buffer) + t.equal(impl.Buffer.from(new Uint8Array([0, 42, 3])).constructor, buffer.Buffer) + t.equal(impl.Buffer.from([]).constructor, buffer.Buffer) + }); + [0, 10, 100].forEach(function (arg) { + t.equal(dangerous.Buffer.allocUnsafe(arg).constructor, buffer.Buffer) + t.equal(dangerous.Buffer.allocUnsafeSlow(arg).constructor, buffer.SlowBuffer(0).constructor) + }) + t.end() +}) + +test('Invalid calls throw', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.throws(function () { impl.Buffer.from(0) }) + t.throws(function () { impl.Buffer.from(10) }) + t.throws(function () { impl.Buffer.from(10, 'utf-8') }) + t.throws(function () { impl.Buffer.from('string', 'invalid encoding') }) + t.throws(function () { impl.Buffer.from(-10) }) + t.throws(function () { impl.Buffer.from(1e90) }) + t.throws(function () { impl.Buffer.from(Infinity) }) + t.throws(function () { impl.Buffer.from(-Infinity) }) + t.throws(function () { impl.Buffer.from(NaN) }) + t.throws(function () { impl.Buffer.from(null) }) + t.throws(function () { impl.Buffer.from(undefined) }) + t.throws(function () { impl.Buffer.from() }) + t.throws(function () { impl.Buffer.from({}) }) + t.throws(function () { impl.Buffer.alloc('') }) + t.throws(function () { impl.Buffer.alloc('string') }) + t.throws(function () { impl.Buffer.alloc('string', 'utf-8') }) + t.throws(function () { impl.Buffer.alloc('b25ldHdvdGhyZWU=', 'base64') }) + t.throws(function () { impl.Buffer.alloc(-10) }) + t.throws(function () { impl.Buffer.alloc(1e90) }) + t.throws(function () { impl.Buffer.alloc(2 * (1 << 30)) }) + t.throws(function () { impl.Buffer.alloc(Infinity) }) + t.throws(function () { impl.Buffer.alloc(-Infinity) }) + t.throws(function () { impl.Buffer.alloc(null) }) + t.throws(function () { impl.Buffer.alloc(undefined) }) + t.throws(function () { impl.Buffer.alloc() }) + t.throws(function () { impl.Buffer.alloc([]) }) + t.throws(function () { impl.Buffer.alloc([0, 42, 3]) }) + t.throws(function () { impl.Buffer.alloc({}) }) + }); + ['allocUnsafe', 'allocUnsafeSlow'].forEach(function (method) { + t.throws(function () { dangerous.Buffer[method]('') }) + t.throws(function () { dangerous.Buffer[method]('string') }) + t.throws(function () { dangerous.Buffer[method]('string', 'utf-8') }) + t.throws(function () { dangerous.Buffer[method](2 * (1 << 30)) }) + t.throws(function () { dangerous.Buffer[method](Infinity) }) + if (dangerous.Buffer[method] === buffer.Buffer.allocUnsafe) { + t.skip('Skipping, older impl of allocUnsafe coerced negative sizes to 0') + } else { + t.throws(function () { dangerous.Buffer[method](-10) }) + t.throws(function () { dangerous.Buffer[method](-1e90) }) + t.throws(function () { dangerous.Buffer[method](-Infinity) }) + } + t.throws(function () { dangerous.Buffer[method](null) }) + t.throws(function () { dangerous.Buffer[method](undefined) }) + t.throws(function () { dangerous.Buffer[method]() }) + t.throws(function () { dangerous.Buffer[method]([]) }) + t.throws(function () { dangerous.Buffer[method]([0, 42, 3]) }) + t.throws(function () { dangerous.Buffer[method]({}) }) + }) + t.end() +}) + +test('Buffers have appropriate lengths', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer.alloc(0).length, 0) + t.equal(impl.Buffer.alloc(10).length, 10) + t.equal(impl.Buffer.from('').length, 0) + t.equal(impl.Buffer.from('string').length, 6) + t.equal(impl.Buffer.from('string', 'utf-8').length, 6) + t.equal(impl.Buffer.from('b25ldHdvdGhyZWU=', 'base64').length, 11) + t.equal(impl.Buffer.from([0, 42, 3]).length, 3) + t.equal(impl.Buffer.from(new Uint8Array([0, 42, 3])).length, 3) + t.equal(impl.Buffer.from([]).length, 0) + }); + ['allocUnsafe', 'allocUnsafeSlow'].forEach(function (method) { + t.equal(dangerous.Buffer[method](0).length, 0) + t.equal(dangerous.Buffer[method](10).length, 10) + }) + t.end() +}) + +test('Buffers have appropriate lengths (2)', function (t) { + t.equal(index.Buffer.alloc, safer.Buffer.alloc) + t.equal(index.Buffer.alloc, dangerous.Buffer.alloc) + var ok = true; + [ safer.Buffer.alloc, + dangerous.Buffer.allocUnsafe, + dangerous.Buffer.allocUnsafeSlow + ].forEach(function (method) { + for (var i = 0; i < 1e2; i++) { + var length = Math.round(Math.random() * 1e5) + var buf = method(length) + if (!buffer.Buffer.isBuffer(buf)) ok = false + if (buf.length !== length) ok = false + } + }) + t.ok(ok) + t.end() +}) + +test('.alloc(size) is zero-filled and has correct length', function (t) { + t.equal(index.Buffer.alloc, safer.Buffer.alloc) + t.equal(index.Buffer.alloc, dangerous.Buffer.alloc) + var ok = true + for (var i = 0; i < 1e2; i++) { + var length = Math.round(Math.random() * 2e6) + var buf = index.Buffer.alloc(length) + if (!buffer.Buffer.isBuffer(buf)) ok = false + if (buf.length !== length) ok = false + var j + for (j = 0; j < length; j++) { + if (buf[j] !== 0) ok = false + } + buf.fill(1) + for (j = 0; j < length; j++) { + if (buf[j] !== 1) ok = false + } + } + t.ok(ok) + t.end() +}) + +test('.allocUnsafe / .allocUnsafeSlow are fillable and have correct lengths', function (t) { + ['allocUnsafe', 'allocUnsafeSlow'].forEach(function (method) { + var ok = true + for (var i = 0; i < 1e2; i++) { + var length = Math.round(Math.random() * 2e6) + var buf = dangerous.Buffer[method](length) + if (!buffer.Buffer.isBuffer(buf)) ok = false + if (buf.length !== length) ok = false + buf.fill(0, 0, length) + var j + for (j = 0; j < length; j++) { + if (buf[j] !== 0) ok = false + } + buf.fill(1, 0, length) + for (j = 0; j < length; j++) { + if (buf[j] !== 1) ok = false + } + } + t.ok(ok, method) + }) + t.end() +}) + +test('.alloc(size, fill) is `fill`-filled', function (t) { + t.equal(index.Buffer.alloc, safer.Buffer.alloc) + t.equal(index.Buffer.alloc, dangerous.Buffer.alloc) + var ok = true + for (var i = 0; i < 1e2; i++) { + var length = Math.round(Math.random() * 2e6) + var fill = Math.round(Math.random() * 255) + var buf = index.Buffer.alloc(length, fill) + if (!buffer.Buffer.isBuffer(buf)) ok = false + if (buf.length !== length) ok = false + for (var j = 0; j < length; j++) { + if (buf[j] !== fill) ok = false + } + } + t.ok(ok) + t.end() +}) + +test('.alloc(size, fill) is `fill`-filled', function (t) { + t.equal(index.Buffer.alloc, safer.Buffer.alloc) + t.equal(index.Buffer.alloc, dangerous.Buffer.alloc) + var ok = true + for (var i = 0; i < 1e2; i++) { + var length = Math.round(Math.random() * 2e6) + var fill = Math.round(Math.random() * 255) + var buf = index.Buffer.alloc(length, fill) + if (!buffer.Buffer.isBuffer(buf)) ok = false + if (buf.length !== length) ok = false + for (var j = 0; j < length; j++) { + if (buf[j] !== fill) ok = false + } + } + t.ok(ok) + t.deepEqual(index.Buffer.alloc(9, 'a'), index.Buffer.alloc(9, 97)) + t.notDeepEqual(index.Buffer.alloc(9, 'a'), index.Buffer.alloc(9, 98)) + + var tmp = new buffer.Buffer(2) + tmp.fill('ok') + if (tmp[1] === tmp[0]) { + // Outdated Node.js + t.deepEqual(index.Buffer.alloc(5, 'ok'), index.Buffer.from('ooooo')) + } else { + t.deepEqual(index.Buffer.alloc(5, 'ok'), index.Buffer.from('okoko')) + } + t.notDeepEqual(index.Buffer.alloc(5, 'ok'), index.Buffer.from('kokok')) + + t.end() +}) + +test('safer.Buffer.from returns results same as Buffer constructor', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.deepEqual(impl.Buffer.from(''), new buffer.Buffer('')) + t.deepEqual(impl.Buffer.from('string'), new buffer.Buffer('string')) + t.deepEqual(impl.Buffer.from('string', 'utf-8'), new buffer.Buffer('string', 'utf-8')) + t.deepEqual(impl.Buffer.from('b25ldHdvdGhyZWU=', 'base64'), new buffer.Buffer('b25ldHdvdGhyZWU=', 'base64')) + t.deepEqual(impl.Buffer.from([0, 42, 3]), new buffer.Buffer([0, 42, 3])) + t.deepEqual(impl.Buffer.from(new Uint8Array([0, 42, 3])), new buffer.Buffer(new Uint8Array([0, 42, 3]))) + t.deepEqual(impl.Buffer.from([]), new buffer.Buffer([])) + }) + t.end() +}) + +test('safer.Buffer.from returns consistent results', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.deepEqual(impl.Buffer.from(''), impl.Buffer.alloc(0)) + t.deepEqual(impl.Buffer.from([]), impl.Buffer.alloc(0)) + t.deepEqual(impl.Buffer.from(new Uint8Array([])), impl.Buffer.alloc(0)) + t.deepEqual(impl.Buffer.from('string', 'utf-8'), impl.Buffer.from('string')) + t.deepEqual(impl.Buffer.from('string'), impl.Buffer.from([115, 116, 114, 105, 110, 103])) + t.deepEqual(impl.Buffer.from('string'), impl.Buffer.from(impl.Buffer.from('string'))) + t.deepEqual(impl.Buffer.from('b25ldHdvdGhyZWU=', 'base64'), impl.Buffer.from('onetwothree')) + t.notDeepEqual(impl.Buffer.from('b25ldHdvdGhyZWU='), impl.Buffer.from('onetwothree')) + }) + t.end() +}) diff --git a/node_modules/urlsafe-base64/.npmignore b/node_modules/urlsafe-base64/.npmignore new file mode 100644 index 0000000..8b21ad5 --- /dev/null +++ b/node_modules/urlsafe-base64/.npmignore @@ -0,0 +1,6 @@ +.DS_Store +.git* +.travis* +Makefile +test/ +*.tmproj \ No newline at end of file diff --git a/node_modules/urlsafe-base64/index.js b/node_modules/urlsafe-base64/index.js new file mode 100644 index 0000000..7e21c90 --- /dev/null +++ b/node_modules/urlsafe-base64/index.js @@ -0,0 +1,2 @@ + +module.exports = require('./lib/urlsafe-base64'); \ No newline at end of file diff --git a/node_modules/urlsafe-base64/lib/urlsafe-base64.js b/node_modules/urlsafe-base64/lib/urlsafe-base64.js new file mode 100644 index 0000000..7f26afa --- /dev/null +++ b/node_modules/urlsafe-base64/lib/urlsafe-base64.js @@ -0,0 +1,77 @@ +/*! + * urlsafe-base64 + */ + +/** + * Module Dependencies + */ + +// None yet! + +/** + * Library version. + */ + +exports.version = '1.0.0'; + +/** + * .encode + * + * return an encoded Buffer as URL Safe Base64 + * + * Note: This function encodes to the RFC 4648 Spec where '+' is encoded + * as '-' and '/' is encoded as '_'. The padding character '=' is + * removed. + * + * @param {Buffer} buffer + * @return {String} + * @api public + */ + +exports.encode = function encode(buffer) { + + return buffer.toString('base64') + .replace(/\+/g, '-') // Convert '+' to '-' + .replace(/\//g, '_') // Convert '/' to '_' + .replace(/=+$/, ''); // Remove ending '=' + +}; + +/** + * .decode + * + * return an decoded URL Safe Base64 as Buffer + * + * @param {String} + * @return {Buffer} + * @api public + */ + +exports.decode = function decode(base64) { + + // Add removed at end '=' + base64 += Array(5 - base64.length % 4).join('='); + + base64 = base64 + .replace(/\-/g, '+') // Convert '-' to '+' + .replace(/\_/g, '/'); // Convert '_' to '/' + + return new Buffer(base64, 'base64'); + +}; + +/** + * .validate + * + * Validates a string if it is URL Safe Base64 encoded. + * + * @param {String} + * @return {Boolean} + * @api public + */ + +exports.validate = function validate(base64) { + + return /^[A-Za-z0-9\-_]+$/.test(base64); + +}; \ No newline at end of file diff --git a/node_modules/urlsafe-base64/package.json b/node_modules/urlsafe-base64/package.json new file mode 100644 index 0000000..b40a58f --- /dev/null +++ b/node_modules/urlsafe-base64/package.json @@ -0,0 +1,59 @@ +{ + "_from": "urlsafe-base64@^1.0.0", + "_id": "urlsafe-base64@1.0.0", + "_inBundle": false, + "_integrity": "sha1-I/iQaabGL0bPOh07ABac77kL4MY=", + "_location": "/urlsafe-base64", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "urlsafe-base64@^1.0.0", + "name": "urlsafe-base64", + "escapedName": "urlsafe-base64", + "rawSpec": "^1.0.0", + "saveSpec": null, + "fetchSpec": "^1.0.0" + }, + "_requiredBy": [ + "/http_ece", + "/web-push" + ], + "_resolved": "https://registry.npmjs.org/urlsafe-base64/-/urlsafe-base64-1.0.0.tgz", + "_shasum": "23f89069a6c62f46cf3a1d3b00169cefb90be0c6", + "_spec": "urlsafe-base64@^1.0.0", + "_where": "D:\\Users\\user\\Documents\\Portofolio\\Github\\WebsiteFootballPWA\\node_modules\\web-push", + "author": { + "name": "RGBboy", + "email": "l-_-l@rgbboy.com" + }, + "bugs": { + "url": "https://github.com/RGBboy/urlsafe-base64/issues" + }, + "bundleDependencies": false, + "dependencies": {}, + "deprecated": false, + "description": "URL Safe Base64 encoding", + "devDependencies": { + "mocha": "1.5.x", + "should": "1.2.x" + }, + "homepage": "https://github.com/RGBboy/urlsafe-base64#readme", + "keywords": [ + "base64", + "encoding", + "url", + "util" + ], + "main": "index", + "name": "urlsafe-base64", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/RGBboy/urlsafe-base64.git" + }, + "scripts": { + "test": "make test", + "unit": "make unit" + }, + "version": "1.0.0" +} diff --git a/node_modules/urlsafe-base64/readme.md b/node_modules/urlsafe-base64/readme.md new file mode 100644 index 0000000..eb054c6 --- /dev/null +++ b/node_modules/urlsafe-base64/readme.md @@ -0,0 +1,84 @@ +# URL Safe Base64 + +URL Safe Base64 util module for Node.js applications + +[![Build Status](https://secure.travis-ci.org/RGBboy/urlsafe-base64.png)](http://travis-ci.org/RGBboy/urlsafe-base64) + +## Installation + +With [npm](http://npmjs.org) do: + +``` +npm install urlsafe-base64 +``` + +## Usage + +Require it within your module: + +``` javascript + var URLSafeBase64 = require('urlsafe-base64'); +``` + +### .encode(buffer) + +Encodes a buffer as a URL Safe Base64 string. This function encodes to +the RFC 4648 Spec where '+' is encoded as '-' and '/' is encoded as '_'. +The padding character '=' is removed. + +``` javascript + var randomURLSafeBase64; + crypto.randomBytes(32, function(err, buf) { + if (err) { + throw err; + return; + }; + randomURLSafeBase64 = URLSafeBase64.encode(buf); + }); +``` + +### .decode(string) + +Decodes a URL Safe Base64 string as a buffer. + +``` javascript +var someURLSafeBase64 = ''; +URLSafeBase64.decode(someURLSafeBase64); // returns a buffer +``` + +### .validate(string) + +Validates a string if it is URL Safe Base64 encoded. + +``` javascript + var validURLSafeBase64 = ''; + URLSafeBase64.validate(validURLSafeBase64); // returns true + + var invalidURLSafeBase64 = '/+==' + URLSafeBase64.validate(invalidURLSafeBase64); // returns false +``` + +## License + +(The MIT License) + +Copyright (c) 2014 RGBboy <l-_-l@rgbboy.com> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/web-push/LICENSE b/node_modules/web-push/LICENSE new file mode 100644 index 0000000..94e7dd6 --- /dev/null +++ b/node_modules/web-push/LICENSE @@ -0,0 +1,5 @@ +Copyright 2015 Marco Castelluccio + +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/. diff --git a/node_modules/web-push/README.md b/node_modules/web-push/README.md new file mode 100644 index 0000000..57427a4 --- /dev/null +++ b/node_modules/web-push/README.md @@ -0,0 +1,562 @@ +

    web-push

    + +

    + + Travis Build Status + + + NPM Dependency State + + + NPM Dev Dependency State + +

    + +# Why + +Web push requires that push messages triggered from a backend be done via the +[Web Push Protocol](https://tools.ietf.org/html/draft-ietf-webpush-protocol) +and if you want to send data with your push message, you must also encrypt +that data according to the [Message Encryption for Web Push spec](https://tools.ietf.org/html/draft-ietf-webpush-encryption). + +This module makes it easy to send messages and will also handle legacy support +for browsers relying on GCM for message sending / delivery. + +# Install + +Installation is simple, just install via npm. + + npm install web-push --save + +# Usage + +The common use case for this library is an application server using +a GCM API key and VAPID keys. + +```javascript +const webpush = require('web-push'); + +// VAPID keys should only be generated only once. +const vapidKeys = webpush.generateVAPIDKeys(); + +webpush.setGCMAPIKey(''); +webpush.setVapidDetails( + 'mailto:example@yourdomain.org', + vapidKeys.publicKey, + vapidKeys.privateKey +); + +// This is the same output of calling JSON.stringify on a PushSubscription +const pushSubscription = { + endpoint: '.....', + keys: { + auth: '.....', + p256dh: '.....' + } +}; + +webpush.sendNotification(pushSubscription, 'Your Push Payload Text'); +``` + +## Using VAPID Key for applicationServerKey + +When using your VAPID key in your web app, you'll need to convert the +URL safe base64 string to a Uint8Array to pass into the subscribe call, +which you can do like so: + +```javascript +function urlBase64ToUint8Array(base64String) { + const padding = '='.repeat((4 - base64String.length % 4) % 4); + const base64 = (base64String + padding) + .replace(/-/g, '+') + .replace(/_/g, '/'); + + const rawData = window.atob(base64); + const outputArray = new Uint8Array(rawData.length); + + for (let i = 0; i < rawData.length; ++i) { + outputArray[i] = rawData.charCodeAt(i); + } + return outputArray; +} + +const vapidPublicKey = ''; +const convertedVapidKey = urlBase64ToUint8Array(vapidPublicKey); + +registration.pushManager.subscribe({ + userVisibleOnly: true, + applicationServerKey: convertedVapidKey +}); +``` + +## Command Line + +You can install `web-push` globally and use it for sending notifications +and / or generating VAPID keys. + +Install like so: + + npm install web-push -g + +Then you can run the following commands: + + Usage: + + web-push send-notification --endpoint= [--key=] [--auth=] [--payload=] [--encoding=] [--ttl=] [--vapid-subject=] [--vapid-pubkey=] [--vapid-pvtkey=] [--gcm-api-key=] + + web-push generate-vapid-keys [--json] + + +# API Reference + +## sendNotification(pushSubscription, payload, options) + +```javascript +const pushSubscription = { + endpoint: '< Push Subscription URL >', + keys: { + p256dh: '< User Public Encryption Key >', + auth: '< User Auth Secret >' + } +}; + +const payload = '< Push Payload String >'; + +const options = { + gcmAPIKey: '< GCM API Key >', + vapidDetails: { + subject: '< \'mailto\' Address or URL >', + publicKey: '< URL Safe Base64 Encoded Public Key >', + privateKey: '< URL Safe Base64 Encoded Private Key >' + }, + timeout: + TTL: , + headers: { + '< header name >': '< header value >' + }, + contentEncoding: '< Encoding type, e.g.: aesgcm or aes128gcm >', + proxy: '< proxy server options >', + agent: '< https.Agent instance >' +} + +webpush.sendNotification( + pushSubscription, + payload, + options +); +``` + +> **Note:** `sendNotification()` you don't need to define a payload, and this +method will work without a GCM API Key and / or VAPID keys if the push service +supports it. + +### Input + +**Push Subscription** + +The first argument must be an object containing the details for a push +subscription. + +The expected format is the same output as JSON.stringify'ing a PushSubscription +in the browser. + +**Payload** + +The payload is optional, but if set, will be the data sent with a push +message. + +This must be either a *string* or a node +[*Buffer*](https://nodejs.org/api/buffer.html). + +> **Note:** In order to encrypt the *payload*, the *pushSubscription* **must** +have a *keys* object with *p256dh* and *auth* values. + +**Options** + +Options is an optional argument that if defined should be an object containing +any of the following values defined, although none of them are required. + +- **gcmAPIKey** can be a GCM API key to be used for this request and this +request only. This overrides any API key set via `setGCMAPIKey()`. +- **vapidDetails** should be an object with *subject*, *publicKey* and +*privateKey* values defined. These values should follow the [VAPID Spec](https://tools.ietf.org/html/draft-thomson-webpush-vapid). +- **timeout** is a value in milliseconds that specifies how long the library must wait for a response from the push service before timing out (by default undefined). +- **TTL** is a value in seconds that describes how long a push message is +retained by the push service (by default, four weeks). +- **headers** is an object with all the extra headers you want to add to the request. +- **contentEncoding** is the type of push encoding to use (e.g. 'aes128gcm', by default, or 'aesgcm'). +- **proxy** is the [HttpsProxyAgent's constructor argument](https://github.com/TooTallNate/node-https-proxy-agent#new-httpsproxyagentobject-options) +that may either be a string URI of the proxy server (eg. http://< hostname >:< port >) +or an "options" object with more specific properties. +- **agent** is the [HTTPS Agent instance](https://nodejs.org/dist/latest/docs/api/https.html#https_class_https_agent) which will be used in the `https.request` method. If the `proxy` options defined, `agent` will be ignored! + +### Returns + +A promise that resolves if the notification was sent successfully +with details of the request, otherwise it rejects. + +In both cases, resolving or rejecting, you'll be able to access the following +values on the returned object or error. + +- *statusCode*, the status code of the response from the push service; +- *headers*, the headers of the response from the push service; +- *body*, the body of the response from the push service. + +
    + +## generateVAPIDKeys() + +```javascript +const vapidKeys = webpush.generateVAPIDKeys(); + +// Prints 2 URL Safe Base64 Encoded Strings +console.log(vapidKeys.publicKey, vapidKeys.privateKey); +``` + +### Input + +None. + +### Returns + +Returns an object with **publicKey** and **privateKey** values which are +URL Safe Base64 encoded strings. + +> **Note:** You should create these keys once, store them and use them for all +> future messages you send. + +
    + +## setGCMAPIKey(apiKey) + +```javascript +webpush.setGCMAPIKey('Your GCM API Key'); +``` + +### Input + +This method expects the GCM API key that is linked to the `gcm_sender_id ` in +your web app manifest. + +You can use a GCM API Key from the Google Developer Console or the +*Cloud Messaging* tab under a Firebase Project. + +### Returns + +None. + +
    + +## encrypt(userPublicKey, userAuth, payload, contentEncoding) + +```javascript +const pushSubscription = { + endpoint: 'https://....', + keys: { + p256dh: '.....', + auth: '.....' + } +}; +webPush.encrypt( + pushSubscription.keys.p256dh, + pushSubscription.keys.auth, + 'My Payload', + 'aes128gcm' +) +.then(encryptionDetails => { + +}); +``` + +Encrypts the payload according to the [Message Encryption for Web +Push](https://webpush-wg.github.io/webpush-encryption/) standard. + +> (*sendNotification* will automatically encrypt the payload for you, so if +> you use *sendNotification* you don't need to worry about it). + +### Input + +The `encrypt()` method expects the following input: + +- *userPublicKey*: the public key of the receiver (from the browser). +- *userAuth*: the auth secret of the receiver (from the browser). +- *payload*: the message to attach to the notification. +- *contentEncoding*: the type of content encoding to use (e.g. aesgcm or aes128gcm). + +### Returns + +This method returns an object with the following fields: + +- *localPublicKey*: The public key matched the private key used during +encryption. +- *salt*: A string representing the salt used to encrypt the payload. +- *cipherText*: The encrypted payload as a Buffer. + +
    + +## getVapidHeaders(audience, subject, publicKey, privateKey, contentEncoding, expiration) + +```javascript +const parsedUrl = url.parse(subscription.endpoint); +const audience = parsedUrl.protocol + '//' + + parsedUrl.hostname; + +const vapidHeaders = vapidHelper.getVapidHeaders( + audience, + 'mailto: example@web-push-node.org', + vapidDetails.publicKey, + vapidDetails.privateKey, + 'aes128gcm' +); +``` + +The *getVapidHeaders()* method will take in the values needed to create +an Authorization and Crypto-Key header. + +### Input + +The `getVapidHeaders()` method expects the following input: + +- *audience*: the origin of the **push service**. +- *subject*: the mailto or URL for your application. +- *publicKey*: the VAPID public key. +- *privateKey*: the VAPID private key. +- *contentEncoding*: the type of content encoding to use (e.g. aesgcm or aes128gcm). + +### Returns + +This method returns an object with the following fields: + +- *localPublicKey*: The public key matched the private key used during +encryption. +- *salt*: A string representing the salt used to encrypt the payload. +- *cipherText*: The encrypted payload as a Buffer. + +
    + +## generateRequestDetails(pushSubscription, payload, options) + +```javascript +const pushSubscription = { + endpoint: '< Push Subscription URL >'; + keys: { + p256dh: '< User Public Encryption Key >', + auth: '< User Auth Secret >' + } +}; + +const payload = '< Push Payload String >'; + +const options = { + gcmAPIKey: '< GCM API Key >', + vapidDetails: { + subject: '< \'mailto\' Address or URL >', + publicKey: '< URL Safe Base64 Encoded Public Key >', + privateKey: '< URL Safe Base64 Encoded Private Key >', + } + TTL: , + headers: { + '< header name >': '< header value >' + }, + contentEncoding: '< Encoding type, e.g.: aesgcm or aes128gcm >', + proxy: '< proxy server options >' +} + +try { + const details = webpush.generateRequestDetails( + pushSubscription, + payload, + options + ); +} catch (err) { + console.error(err); +} +``` + +> **Note:** When calling `generateRequestDetails()` the payload argument +does not *need* to be defined, passing in null will return no body and +> exclude any unnecessary headers. +> Headers related to the GCM API Key and / or VAPID keys will be included +> if supplied and required. + +### Input + +**Push Subscription** + +The first argument must be an object containing the details for a push +subscription. + +The expected format is the same output as JSON.stringify'ing a PushSubscription +in the browser. + +**Payload** + +The payload is optional, but if set, will be encrypted and a [*Buffer*](https://nodejs.org/api/buffer.html) + will be returned via the `payload` parameter. + +This argument must be either a *string* or a node +[*Buffer*](https://nodejs.org/api/buffer.html). + +> **Note:** In order to encrypt the *payload*, the *pushSubscription* **must** +have a *keys* object with *p256dh* and *auth* values. + +**Options** + +Options is an optional argument that if defined should be an object containing +any of the following values defined, although none of them are required. + +- **gcmAPIKey** can be a GCM API key to be used for this request and this +request only. This overrides any API key set via `setGCMAPIKey()`. +- **vapidDetails** should be an object with *subject*, *publicKey* and +*privateKey* values defined. These values should follow the [VAPID Spec](https://tools.ietf.org/html/draft-thomson-webpush-vapid). +- **TTL** is a value in seconds that describes how long a push message is +retained by the push service (by default, four weeks). +- **headers** is an object with all the extra headers you want to add to the request. +- **contentEncoding** is the type of push encoding to use (e.g. 'aesgcm', by default, or 'aes128gcm'). +- **proxy** is the [HttpsProxyAgent's constructor argument](https://github.com/TooTallNate/node-https-proxy-agent#new-httpsproxyagentobject-options) +that may either be a string URI of the proxy server (eg. http://< hostname >:< port >) +or an "options" object with more specific properties. + +### Returns + +An object containing all the details needed to make a network request, the +object will contain: + +- *endpoint*, the URL to send the request to; +- *method*, this will be 'POST'; +- *headers*, the headers to add to the request; +- *body*, the body of the request (As a Node Buffer). + +
    + +# Browser Support + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    BrowserPush without PayloadPush with PayloadVAPIDNotes
    Chrome✓ v42+✓ v50+✓ v52+In v51 and less, the `gcm_sender_id` is needed to get a push subscription.
    Edge✓ v17+ (April 2018)✓ v17+ (April 2018)✓ v17+ (April 2018)
    Firefox✓ v44+✓ v44+✓ v46+
    Opera✓ v39+ *✓ v39+ * + * Opera supports push on Android but not on desktop. +
    +
    + The `gcm_sender_id` is needed to get a push subscription. +
    Safari
    Samsung Internet Browser✓ v4.0.10-53+✓ v5.0.30-40+The `gcm_sender_id` is needed to get a push subscription.
    + +# Help + +**Service Worker Cookbook** + +The [Service Worker Cookbook](https://serviceworke.rs/) is full of Web Push +examples using this library. + +# Running tests + +> Prerequisites: +> * Java JDK or JRE (http://www.oracle.com/technetwork/java/javase/downloads/index.html) + +To run tests: + + npm test + +

    + + + +

    diff --git a/node_modules/web-push/package.json b/node_modules/web-push/package.json new file mode 100644 index 0000000..b37362c --- /dev/null +++ b/node_modules/web-push/package.json @@ -0,0 +1,89 @@ +{ + "_from": "web-push", + "_id": "web-push@3.4.4", + "_inBundle": false, + "_integrity": "sha512-tB0F+ccobsfw5jTWBinWJKyd/YdCdRbKj+CFSnsJeEgFYysOULvWFYyeCxn9KuQvG/3UF1t3cTAcJzBec5LCWA==", + "_location": "/web-push", + "_phantomChildren": {}, + "_requested": { + "type": "tag", + "registry": true, + "raw": "web-push", + "name": "web-push", + "escapedName": "web-push", + "rawSpec": "", + "saveSpec": null, + "fetchSpec": "latest" + }, + "_requiredBy": [ + "#DEV:/", + "#USER" + ], + "_resolved": "https://registry.npmjs.org/web-push/-/web-push-3.4.4.tgz", + "_shasum": "b11523ada0f4b8c2481f65d1d059acd45ba27ca0", + "_spec": "web-push", + "_where": "D:\\Users\\user\\Documents\\Portofolio\\Github\\WebsiteFootballPWA", + "author": { + "name": "Marco Castelluccio" + }, + "bin": { + "web-push": "src/cli.js" + }, + "bugs": { + "url": "https://github.com/web-push-libs/web-push/issues" + }, + "bundleDependencies": false, + "dependencies": { + "asn1.js": "^5.3.0", + "http_ece": "1.1.0", + "https-proxy-agent": "^5.0.0", + "jws": "^4.0.0", + "minimist": "^1.2.5", + "urlsafe-base64": "^1.0.0" + }, + "deprecated": false, + "description": "Web Push library for Node.js", + "devDependencies": { + "chalk": "4.0.0", + "chromedriver": "81.0.0", + "coveralls": "3.0.9", + "del": "5.1.0", + "eslint": "7.0.0", + "eslint-config-airbnb": "18.1.0", + "eslint-plugin-import": "2.20.2", + "geckodriver": "1.19.1", + "istanbul": "0.4.5", + "mkdirp": "1.0.4", + "mocha": "7.1.2", + "mocha-lcov-reporter": "1.3.0", + "portfinder": "1.0.26", + "selenium-assistant": "5.4.0", + "sinon": "7.5.0", + "which": "2.0.2" + }, + "engines": { + "node": ">= 6" + }, + "homepage": "https://github.com/web-push-libs/web-push#readme", + "keywords": [ + "web push", + "push", + "notifications", + "push notifications" + ], + "license": "MPL-2.0", + "main": "src/index.js", + "name": "web-push", + "repository": { + "type": "git", + "url": "git+https://github.com/web-push-libs/web-push.git" + }, + "scripts": { + "coveralls": "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js", + "download-browser": "node --harmony ./test/helpers/download-test-browsers.js", + "lint": "node ./node_modules/eslint/bin/eslint --ignore-path .gitignore '.'", + "pretest": "npm run lint && npm run download-browser", + "test": "node --harmony node_modules/.bin/istanbul cover node_modules/.bin/_mocha -- --ui tdd test/test*" + }, + "version": "3.4.4" +} diff --git a/node_modules/web-push/src/cli.js b/node_modules/web-push/src/cli.js new file mode 100644 index 0000000..50bf11d --- /dev/null +++ b/node_modules/web-push/src/cli.js @@ -0,0 +1,126 @@ +#! /usr/bin/env node +/* eslint consistent-return:0 */ + +'use strict'; + +const webPush = require('../src/index.js'); + +const printUsageDetails = () => { + const actions = [ + { + name: 'send-notification', + options: [ + '--endpoint=', + '[--key=]', + '[--auth=]', + '[--payload=]', + '[--ttl=]', + '[--encoding=]', + '[--vapid-subject=]', + '[--vapid-pubkey=]', + '[--vapid-pvtkey=]', + '[--gcm-api-key=]' + ] + }, { + name: 'generate-vapid-keys', + options: [ + '[--json]' + ] + } + ]; + + let usage = '\nUsage: \n\n'; + actions.forEach(action => { + usage += ' web-push ' + action.name; + usage += ' ' + action.options.join(' '); + usage += '\n\n'; + }); + + console.log(usage); + process.exit(1); +}; + +const generateVapidKeys = returnJson => { + const vapidKeys = webPush.generateVAPIDKeys(); + + let outputText; + if (returnJson) { + outputText = JSON.stringify(vapidKeys); + } else { + const outputLine = '\n=======================================\n'; + outputText = outputLine + '\n' + + 'Public Key:\n' + vapidKeys.publicKey + '\n\n' + + 'Private Key:\n' + vapidKeys.privateKey + '\n' + + outputLine; + } + + console.log(outputText); + process.exit(0); +}; + +const sendNotification = args => { + if (process.env.GCM_API_KEY) { + webPush.setGCMAPIKey(process.env.GCM_API_KEY); + } + + const subscription = { + endpoint: args.endpoint, + keys: { + p256dh: args.key || null, + auth: args.auth || null + } + }; + + const payload = args.payload || null; + + const options = {}; + + if (args.ttl) { + options.TTL = args.ttl; + } + + if (argv['vapid-subject'] || argv['vapid-pubkey'] || argv['vapid-pvtkey']) { + options.vapidDetails = { + subject: args['vapid-subject'] || null, + publicKey: args['vapid-pubkey'] || null, + privateKey: args['vapid-pvtkey'] || null + }; + } + + if (args['gcm-api-key']) { + options.gcmAPIKey = args['gcm-api-key']; + } + + if (args.encoding) { + options.contentEncoding = args.encoding; + } + + webPush.sendNotification(subscription, payload, options) + .then(() => { + console.log('Push message sent.'); + }, err => { + console.log('Error sending push message: '); + console.log(err); + }) + .then(() => { + process.exit(0); + }); +}; + +const action = process.argv[2]; +const argv = require('minimist')(process.argv.slice(3)); +switch (action) { + case 'send-notification': + if (!argv.endpoint) { + return printUsageDetails(); + } + + sendNotification(argv); + break; + case 'generate-vapid-keys': + generateVapidKeys(argv.json || false); + break; + default: + printUsageDetails(); + break; +} diff --git a/node_modules/web-push/src/encryption-helper.js b/node_modules/web-push/src/encryption-helper.js new file mode 100644 index 0000000..321d3ee --- /dev/null +++ b/node_modules/web-push/src/encryption-helper.js @@ -0,0 +1,63 @@ +'use strict'; + +const crypto = require('crypto'); +const ece = require('http_ece'); +const urlBase64 = require('urlsafe-base64'); + +const encrypt = function(userPublicKey, userAuth, payload, contentEncoding) { + if (!userPublicKey) { + throw new Error('No user public key provided for encryption.'); + } + + if (typeof userPublicKey !== 'string') { + throw new Error('The subscription p256dh value must be a string.'); + } + + if (urlBase64.decode(userPublicKey).length !== 65) { + throw new Error('The subscription p256dh value should be 65 bytes long.'); + } + + if (!userAuth) { + throw new Error('No user auth provided for encryption.'); + } + + if (typeof userAuth !== 'string') { + throw new Error('The subscription auth key must be a string.'); + } + + if (urlBase64.decode(userAuth).length < 16) { + throw new Error('The subscription auth key should be at least 16 ' + + 'bytes long'); + } + + if (typeof payload !== 'string' && !Buffer.isBuffer(payload)) { + throw new Error('Payload must be either a string or a Node Buffer.'); + } + + if (typeof payload === 'string' || payload instanceof String) { + payload = Buffer.from(payload); + } + + const localCurve = crypto.createECDH('prime256v1'); + const localPublicKey = localCurve.generateKeys(); + + const salt = urlBase64.encode(crypto.randomBytes(16)); + + const cipherText = ece.encrypt(payload, { + version: contentEncoding, + dh: userPublicKey, + privateKey: localCurve, + salt: salt, + authSecret: userAuth + }); + + return { + localPublicKey: localPublicKey, + salt: salt, + cipherText: cipherText + }; +}; + +module.exports = { + encrypt: encrypt +}; diff --git a/node_modules/web-push/src/index.js b/node_modules/web-push/src/index.js new file mode 100644 index 0000000..d3cd06b --- /dev/null +++ b/node_modules/web-push/src/index.js @@ -0,0 +1,21 @@ +'use strict'; + +const vapidHelper = require('./vapid-helper.js'); +const encryptionHelper = require('./encryption-helper.js'); +const WebPushLib = require('./web-push-lib.js'); +const WebPushError = require('./web-push-error.js'); +const WebPushConstants = require('./web-push-constants.js'); + +const webPush = new WebPushLib(); + +module.exports = { + WebPushError: WebPushError, + supportedContentEncodings: WebPushConstants.supportedContentEncodings, + encrypt: encryptionHelper.encrypt, + getVapidHeaders: vapidHelper.getVapidHeaders, + generateVAPIDKeys: vapidHelper.generateVAPIDKeys, + setGCMAPIKey: webPush.setGCMAPIKey, + setVapidDetails: webPush.setVapidDetails, + generateRequestDetails: webPush.generateRequestDetails, + sendNotification: webPush.sendNotification +}; diff --git a/node_modules/web-push/src/vapid-helper.js b/node_modules/web-push/src/vapid-helper.js new file mode 100644 index 0000000..02fa4ad --- /dev/null +++ b/node_modules/web-push/src/vapid-helper.js @@ -0,0 +1,238 @@ +'use strict'; + +const crypto = require('crypto'); +const urlBase64 = require('urlsafe-base64'); +const asn1 = require('asn1.js'); +const jws = require('jws'); +const url = require('url'); + +const WebPushConstants = require('./web-push-constants.js'); + +/** + * DEFAULT_EXPIRATION is set to seconds in 12 hours + */ +const DEFAULT_EXPIRATION_SECONDS = 12 * 60 * 60; + +// Maximum expiration is 24 hours according. (See VAPID spec) +const MAX_EXPIRATION_SECONDS = 24 * 60 * 60; + +const ECPrivateKeyASN = asn1.define('ECPrivateKey', function() { + this.seq().obj( + this.key('version').int(), + this.key('privateKey').octstr(), + this.key('parameters').explicit(0).objid() + .optional(), + this.key('publicKey').explicit(1).bitstr() + .optional() + ); +}); + +function toPEM(key) { + return ECPrivateKeyASN.encode({ + version: 1, + privateKey: key, + parameters: [1, 2, 840, 10045, 3, 1, 7] // prime256v1 + }, 'pem', { + label: 'EC PRIVATE KEY' + }); +} + +function generateVAPIDKeys() { + const curve = crypto.createECDH('prime256v1'); + curve.generateKeys(); + + let publicKeyBuffer = curve.getPublicKey(); + let privateKeyBuffer = curve.getPrivateKey(); + + // Occassionally the keys will not be padded to the correct lengh resulting + // in errors, hence this padding. + // See https://github.com/web-push-libs/web-push/issues/295 for history. + if (privateKeyBuffer.length < 32) { + const padding = Buffer.alloc(32 - privateKeyBuffer.length); + padding.fill(0); + privateKeyBuffer = Buffer.concat([padding, privateKeyBuffer]); + } + + if (publicKeyBuffer.length < 65) { + const padding = Buffer.alloc(65 - publicKeyBuffer.length); + padding.fill(0); + publicKeyBuffer = Buffer.concat([padding, publicKeyBuffer]); + } + + return { + publicKey: urlBase64.encode(publicKeyBuffer), + privateKey: urlBase64.encode(privateKeyBuffer) + }; +} + +function validateSubject(subject) { + if (!subject) { + throw new Error('No subject set in vapidDetails.subject.'); + } + + if (typeof subject !== 'string' || subject.length === 0) { + throw new Error('The subject value must be a string containing a URL or ' + + 'mailto: address. ' + subject); + } + + if (subject.indexOf('mailto:') !== 0) { + const subjectParseResult = url.parse(subject); + if (!subjectParseResult.hostname) { + throw new Error('Vapid subject is not a url or mailto url. ' + subject); + } + } +} + +function validatePublicKey(publicKey) { + if (!publicKey) { + throw new Error('No key set vapidDetails.publicKey'); + } + + if (typeof publicKey !== 'string') { + throw new Error('Vapid public key is must be a URL safe Base 64 ' + + 'encoded string.'); + } + + publicKey = urlBase64.decode(publicKey); + + if (publicKey.length !== 65) { + throw new Error('Vapid public key should be 65 bytes long when decoded.'); + } +} + +function validatePrivateKey(privateKey) { + if (!privateKey) { + throw new Error('No key set in vapidDetails.privateKey'); + } + + if (typeof privateKey !== 'string') { + throw new Error('Vapid private key must be a URL safe Base 64 ' + + 'encoded string.'); + } + + privateKey = urlBase64.decode(privateKey); + + if (privateKey.length !== 32) { + throw new Error('Vapid private key should be 32 bytes long when decoded.'); + } +} + +/** + * Given the number of seconds calculates + * the expiration in the future by adding the passed `numSeconds` + * with the current seconds from Unix Epoch + * + * @param {Number} numSeconds Number of seconds to be added + * @return {Number} Future expiration in seconds + */ +function getFutureExpirationTimestamp(numSeconds) { + const futureExp = new Date(); + futureExp.setSeconds(futureExp.getSeconds() + numSeconds); + return Math.floor(futureExp.getTime() / 1000); +} + +/** + * Validates the Expiration Header based on the VAPID Spec + * Throws error of type `Error` if the expiration is not validated + * + * @param {Number} expiration Expiration seconds from Epoch to be validated + */ +function validateExpiration(expiration) { + if (!Number.isInteger(expiration)) { + throw new Error('`expiration` value must be a number'); + } + + if (expiration < 0) { + throw new Error('`expiration` must be a positive integer'); + } + + // Roughly checks the time of expiration, since the max expiration can be ahead + // of the time than at the moment the expiration was generated + const maxExpirationTimestamp = getFutureExpirationTimestamp(MAX_EXPIRATION_SECONDS); + + if (expiration >= maxExpirationTimestamp) { + throw new Error('`expiration` value is greater than maximum of 24 hours'); + } +} + +/** + * This method takes the required VAPID parameters and returns the required + * header to be added to a Web Push Protocol Request. + * @param {string} audience This must be the origin of the push service. + * @param {string} subject This should be a URL or a 'mailto:' email + * address. + * @param {string} publicKey The VAPID public key. + * @param {string} privateKey The VAPID private key. + * @param {string} contentEncoding The contentEncoding type. + * @param {integer} [expiration] The expiration of the VAPID JWT. + * @return {Object} Returns an Object with the Authorization and + * 'Crypto-Key' values to be used as headers. + */ +function getVapidHeaders(audience, subject, publicKey, privateKey, contentEncoding, expiration) { + if (!audience) { + throw new Error('No audience could be generated for VAPID.'); + } + + if (typeof audience !== 'string' || audience.length === 0) { + throw new Error('The audience value must be a string containing the ' + + 'origin of a push service. ' + audience); + } + + const audienceParseResult = url.parse(audience); + if (!audienceParseResult.hostname) { + throw new Error('VAPID audience is not a url. ' + audience); + } + + validateSubject(subject); + validatePublicKey(publicKey); + validatePrivateKey(privateKey); + + privateKey = urlBase64.decode(privateKey); + + if (expiration) { + validateExpiration(expiration); + } else { + expiration = getFutureExpirationTimestamp(DEFAULT_EXPIRATION_SECONDS); + } + + const header = { + typ: 'JWT', + alg: 'ES256' + }; + + const jwtPayload = { + aud: audience, + exp: expiration, + sub: subject + }; + + const jwt = jws.sign({ + header: header, + payload: jwtPayload, + privateKey: toPEM(privateKey) + }); + + if (contentEncoding === WebPushConstants.supportedContentEncodings.AES_128_GCM) { + return { + Authorization: 'vapid t=' + jwt + ', k=' + publicKey + }; + } + if (contentEncoding === WebPushConstants.supportedContentEncodings.AES_GCM) { + return { + Authorization: 'WebPush ' + jwt, + 'Crypto-Key': 'p256ecdsa=' + publicKey + }; + } + + throw new Error('Unsupported encoding type specified.'); +} + +module.exports = { + generateVAPIDKeys: generateVAPIDKeys, + getFutureExpirationTimestamp: getFutureExpirationTimestamp, + getVapidHeaders: getVapidHeaders, + validateSubject: validateSubject, + validatePublicKey: validatePublicKey, + validatePrivateKey: validatePrivateKey, + validateExpiration: validateExpiration +}; diff --git a/node_modules/web-push/src/web-push-constants.js b/node_modules/web-push/src/web-push-constants.js new file mode 100644 index 0000000..5ba0979 --- /dev/null +++ b/node_modules/web-push/src/web-push-constants.js @@ -0,0 +1,10 @@ +'use strict'; + +const WebPushConstants = {}; + +WebPushConstants.supportedContentEncodings = { + AES_GCM: 'aesgcm', + AES_128_GCM: 'aes128gcm' +}; + +module.exports = WebPushConstants; diff --git a/node_modules/web-push/src/web-push-error.js b/node_modules/web-push/src/web-push-error.js new file mode 100644 index 0000000..94a1cda --- /dev/null +++ b/node_modules/web-push/src/web-push-error.js @@ -0,0 +1,16 @@ +'use strict'; + +function WebPushError(message, statusCode, headers, body, endpoint) { + Error.captureStackTrace(this, this.constructor); + + this.name = this.constructor.name; + this.message = message; + this.statusCode = statusCode; + this.headers = headers; + this.body = body; + this.endpoint = endpoint; +} + +require('util').inherits(WebPushError, Error); + +module.exports = WebPushError; diff --git a/node_modules/web-push/src/web-push-lib.js b/node_modules/web-push/src/web-push-lib.js new file mode 100644 index 0000000..77dca1c --- /dev/null +++ b/node_modules/web-push/src/web-push-lib.js @@ -0,0 +1,373 @@ +'use strict'; + +const urlBase64 = require('urlsafe-base64'); +const url = require('url'); +const https = require('https'); + +const WebPushError = require('./web-push-error.js'); +const vapidHelper = require('./vapid-helper.js'); +const encryptionHelper = require('./encryption-helper.js'); +const webPushConstants = require('./web-push-constants.js'); + +// Default TTL is four weeks. +const DEFAULT_TTL = 2419200; + +let gcmAPIKey = ''; +let vapidDetails; + +function WebPushLib() { + +} + +/** + * When sending messages to a GCM endpoint you need to set the GCM API key + * by either calling setGMAPIKey() or passing in the API key as an option + * to sendNotification(). + * @param {string} apiKey The API key to send with the GCM request. + */ +WebPushLib.prototype.setGCMAPIKey = function(apiKey) { + if (apiKey === null) { + gcmAPIKey = null; + return; + } + + if (typeof apiKey === 'undefined' + || typeof apiKey !== 'string' + || apiKey.length === 0) { + throw new Error('The GCM API Key should be a non-empty string or null.'); + } + + gcmAPIKey = apiKey; +}; + +/** + * When making requests where you want to define VAPID details, call this + * method before sendNotification() or pass in the details and options to + * sendNotification. + * @param {string} subject This must be either a URL or a 'mailto:' + * address. For example: 'https://my-site.com/contact' or + * 'mailto: contact@my-site.com' + * @param {string} publicKey The public VAPID key, a URL safe, base64 encoded string + * @param {string} privateKey The private VAPID key, a URL safe, base64 encoded string. + */ +WebPushLib.prototype.setVapidDetails = function(subject, publicKey, privateKey) { + if (arguments.length === 1 && arguments[0] === null) { + vapidDetails = null; + return; + } + + vapidHelper.validateSubject(subject); + vapidHelper.validatePublicKey(publicKey); + vapidHelper.validatePrivateKey(privateKey); + + vapidDetails = { + subject: subject, + publicKey: publicKey, + privateKey: privateKey + }; + }; + + /** + * To get the details of a request to trigger a push message, without sending + * a push notification call this method. + * + * This method will throw an error if there is an issue with the input. + * @param {PushSubscription} subscription The PushSubscription you wish to + * send the notification to. + * @param {string|Buffer} [payload] The payload you wish to send to the + * the user. + * @param {Object} [options] Options for the GCM API key and + * vapid keys can be passed in if they are unique for each notification you + * wish to send. + * @return {Object} This method returns an Object which + * contains 'endpoint', 'method', 'headers' and 'payload'. + */ +WebPushLib.prototype.generateRequestDetails = function(subscription, payload, options) { + if (!subscription || !subscription.endpoint) { + throw new Error('You must pass in a subscription with at least ' + + 'an endpoint.'); + } + + if (typeof subscription.endpoint !== 'string' + || subscription.endpoint.length === 0) { + throw new Error('The subscription endpoint must be a string with ' + + 'a valid URL.'); + } + + if (payload) { + // Validate the subscription keys + if (typeof subscription !== 'object' || !subscription.keys + || !subscription.keys.p256dh + || !subscription.keys.auth) { + throw new Error('To send a message with a payload, the ' + + 'subscription must have \'auth\' and \'p256dh\' keys.'); + } + } + + let currentGCMAPIKey = gcmAPIKey; + let currentVapidDetails = vapidDetails; + let timeToLive = DEFAULT_TTL; + let extraHeaders = {}; + let contentEncoding = webPushConstants.supportedContentEncodings.AES_128_GCM; + let proxy; + let agent; + let timeout; + + if (options) { + const validOptionKeys = [ + 'headers', + 'gcmAPIKey', + 'vapidDetails', + 'TTL', + 'contentEncoding', + 'proxy', + 'agent', + 'timeout' + ]; + const optionKeys = Object.keys(options); + for (let i = 0; i < optionKeys.length; i += 1) { + const optionKey = optionKeys[i]; + if (validOptionKeys.indexOf(optionKey) === -1) { + throw new Error('\'' + optionKey + '\' is an invalid option. ' + + 'The valid options are [\'' + validOptionKeys.join('\', \'') + + '\'].'); + } + } + + if (options.headers) { + extraHeaders = options.headers; + let duplicates = Object.keys(extraHeaders) + .filter(function (header) { + return typeof options[header] !== 'undefined'; + }); + + if (duplicates.length > 0) { + throw new Error('Duplicated headers defined [' + + duplicates.join(',') + ']. Please either define the header in the' + + 'top level options OR in the \'headers\' key.'); + } + } + + if (options.gcmAPIKey) { + currentGCMAPIKey = options.gcmAPIKey; + } + + // Falsy values are allowed here so one can skip Vapid `else if` below and use FCM + if (options.vapidDetails !== undefined) { + currentVapidDetails = options.vapidDetails; + } + + if (options.TTL !== undefined) { + timeToLive = Number(options.TTL); + if (timeToLive < 0) { + throw new Error('TTL should be a number and should be at least 0'); + } + } + + if (options.contentEncoding) { + if ((options.contentEncoding === webPushConstants.supportedContentEncodings.AES_128_GCM + || options.contentEncoding === webPushConstants.supportedContentEncodings.AES_GCM)) { + contentEncoding = options.contentEncoding; + } else { + throw new Error('Unsupported content encoding specified.'); + } + } + + if (options.proxy) { + if (typeof options.proxy === 'string' + || typeof options.proxy.host === 'string') { + proxy = options.proxy; + } else { + console.warn('Attempt to use proxy option, but invalid type it should be a string or proxy options object.'); + } + } + + if (options.agent) { + if (options.agent instanceof https.Agent) { + if (proxy) { + console.warn('Agent option will be ignored because proxy option is defined.'); + } + + agent = options.agent; + } else { + console.warn('Wrong type for the agent option, it should be an instance of https.Agent.'); + } + } + + if (typeof options.timeout === 'number') { + timeout = options.timeout; + } + } + + if (typeof timeToLive === 'undefined') { + timeToLive = DEFAULT_TTL; + } + + const requestDetails = { + method: 'POST', + headers: { + TTL: timeToLive + } + }; + Object.keys(extraHeaders).forEach(function (header) { + requestDetails.headers[header] = extraHeaders[header]; + }); + let requestPayload = null; + + if (payload) { + const encrypted = encryptionHelper + .encrypt(subscription.keys.p256dh, subscription.keys.auth, payload, contentEncoding); + + requestDetails.headers['Content-Length'] = encrypted.cipherText.length; + requestDetails.headers['Content-Type'] = 'application/octet-stream'; + + if (contentEncoding === webPushConstants.supportedContentEncodings.AES_128_GCM) { + requestDetails.headers['Content-Encoding'] = webPushConstants.supportedContentEncodings.AES_128_GCM; + } else if (contentEncoding === webPushConstants.supportedContentEncodings.AES_GCM) { + requestDetails.headers['Content-Encoding'] = webPushConstants.supportedContentEncodings.AES_GCM; + requestDetails.headers.Encryption = 'salt=' + encrypted.salt; + requestDetails.headers['Crypto-Key'] = 'dh=' + urlBase64.encode(encrypted.localPublicKey); + } + + requestPayload = encrypted.cipherText; + } else { + requestDetails.headers['Content-Length'] = 0; + } + + const isGCM = subscription.endpoint.indexOf('https://android.googleapis.com/gcm/send') === 0; + const isFCM = subscription.endpoint.indexOf('https://fcm.googleapis.com/fcm/send') === 0; + // VAPID isn't supported by GCM hence the if, else if. + if (isGCM) { + if (!currentGCMAPIKey) { + console.warn('Attempt to send push notification to GCM endpoint, ' + + 'but no GCM key is defined. Please use setGCMApiKey() or add ' + + '\'gcmAPIKey\' as an option.'); + } else { + requestDetails.headers.Authorization = 'key=' + currentGCMAPIKey; + } + } else if (currentVapidDetails) { + const parsedUrl = url.parse(subscription.endpoint); + const audience = parsedUrl.protocol + '//' + + parsedUrl.host; + + const vapidHeaders = vapidHelper.getVapidHeaders( + audience, + currentVapidDetails.subject, + currentVapidDetails.publicKey, + currentVapidDetails.privateKey, + contentEncoding + ); + + requestDetails.headers.Authorization = vapidHeaders.Authorization; + + if (contentEncoding === webPushConstants.supportedContentEncodings.AES_GCM) { + if (requestDetails.headers['Crypto-Key']) { + requestDetails.headers['Crypto-Key'] += ';' + + vapidHeaders['Crypto-Key']; + } else { + requestDetails.headers['Crypto-Key'] = vapidHeaders['Crypto-Key']; + } + } + } else if (isFCM && currentGCMAPIKey) { + requestDetails.headers.Authorization = 'key=' + currentGCMAPIKey; + } + + requestDetails.body = requestPayload; + requestDetails.endpoint = subscription.endpoint; + + if (proxy) { + requestDetails.proxy = proxy; + } + + if (agent) { + requestDetails.agent = agent; + } + + if (timeout) { + requestDetails.timeout = timeout; + } + + return requestDetails; + }; + +/** + * To send a push notification call this method with a subscription, optional + * payload and any options. + * @param {PushSubscription} subscription The PushSubscription you wish to + * send the notification to. + * @param {string|Buffer} [payload] The payload you wish to send to the + * the user. + * @param {Object} [options] Options for the GCM API key and + * vapid keys can be passed in if they are unique for each notification you + * wish to send. + * @return {Promise} This method returns a Promise which + * resolves if the sending of the notification was successful, otherwise it + * rejects. + */ +WebPushLib.prototype.sendNotification = function(subscription, payload, options) { + let requestDetails; + try { + requestDetails = this.generateRequestDetails(subscription, payload, options); + } catch (err) { + return Promise.reject(err); + } + + return new Promise(function(resolve, reject) { + const httpsOptions = {}; + const urlParts = url.parse(requestDetails.endpoint); + httpsOptions.hostname = urlParts.hostname; + httpsOptions.port = urlParts.port; + httpsOptions.path = urlParts.path; + + httpsOptions.headers = requestDetails.headers; + httpsOptions.method = requestDetails.method; + + if (requestDetails.timeout) { + httpsOptions.timeout = requestDetails.timeout; + } + + if (requestDetails.agent) { + httpsOptions.agent = requestDetails.agent; + } + + if (requestDetails.proxy) { + const HttpsProxyAgent = require('https-proxy-agent'); // eslint-disable-line global-require + httpsOptions.agent = new HttpsProxyAgent(requestDetails.proxy); + } + + const pushRequest = https.request(httpsOptions, function(pushResponse) { + let responseText = ''; + + pushResponse.on('data', function(chunk) { + responseText += chunk; + }); + + pushResponse.on('end', function() { + if (pushResponse.statusCode < 200 || pushResponse.statusCode > 299) { + reject(new WebPushError( + 'Received unexpected response code', + pushResponse.statusCode, pushResponse.headers, responseText, requestDetails.endpoint + )); + } else { + resolve({ + statusCode: pushResponse.statusCode, + body: responseText, + headers: pushResponse.headers + }); + } + }); + }); + + pushRequest.on('error', function(e) { + reject(e); + }); + + if (requestDetails.body) { + pushRequest.write(requestDetails.body); + } + + pushRequest.end(); + }); + }; + +module.exports = WebPushLib; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..995740b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,153 @@ +{ + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=", + "dev": true + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "http_ece": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/http_ece/-/http_ece-1.1.0.tgz", + "integrity": "sha512-bptAfCDdPJxOs5zYSe7Y3lpr772s1G346R4Td5LgRUeCwIGpCGDUTJxRrhTNcAXbx37spge0kWEIH7QAYWNTlA==", + "dev": true, + "requires": { + "urlsafe-base64": "~1.0.0" + } + }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "dev": true, + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "dev": true, + "requires": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "urlsafe-base64": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/urlsafe-base64/-/urlsafe-base64-1.0.0.tgz", + "integrity": "sha1-I/iQaabGL0bPOh07ABac77kL4MY=", + "dev": true + }, + "web-push": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/web-push/-/web-push-3.4.4.tgz", + "integrity": "sha512-tB0F+ccobsfw5jTWBinWJKyd/YdCdRbKj+CFSnsJeEgFYysOULvWFYyeCxn9KuQvG/3UF1t3cTAcJzBec5LCWA==", + "dev": true, + "requires": { + "asn1.js": "^5.3.0", + "http_ece": "1.1.0", + "https-proxy-agent": "^5.0.0", + "jws": "^4.0.0", + "minimist": "^1.2.5", + "urlsafe-base64": "^1.0.0" + } + } + } +} diff --git a/push.js b/push.js new file mode 100644 index 0000000..10c995e --- /dev/null +++ b/push.js @@ -0,0 +1,31 @@ +var webPush = require('web-push'); + +const vapidKeys = { + "publicKey": "BGuFovLk-PEOCnx1Q1PKhwZc86aaVSIhopcSfr_ycvc6irGqAv-31EIofflb2yz6gpZaTWxVNoZtKDfvninu8Xc", + "privateKey": "WwZaE8H_sKndMbsr4QYR0RJ5LhSngC2IDj3ogJymDvI" +}; + + +webPush.setVapidDetails( + 'mailto:example@yourdomain.org', + vapidKeys.publicKey, + vapidKeys.privateKey +) +var pushSubscription = { + "endpoint": "https://fcm.googleapis.com/fcm/send/fux_DviBfak:APA91bFWQ13k67PpvwyS49bRytSZw-NAfDLYvpZKI6AxCd-LqbRwoqthd8ytEfaMZBGHB30p54ihtJzWwovqc9MvlDwU-eURhC5KdoWE_jUmlKKy_5UGzXxwVyiWi3mN98uZZ_F0eAQK", + "keys": { + "p256dh": "BLOrMdKk/Hm4sOXZorjZpKM7UXT7QNWBs5qDhBkpcZ6Plyy9LopcPWioEEAh58OyjgPGjtQvHNL45DF/RDgrAMU=", + "auth": "e9uPIb5O8Ru2zh0eGZdJdQ==" + } +}; +var payload = 'Welcome to Football Watch!'; + +var options = { + gcmAPIKey: '411668443247', + TTL: 60 +}; +webPush.sendNotification( + pushSubscription, + payload, + options +); \ No newline at end of file diff --git a/script/api.js b/script/api.js new file mode 100644 index 0000000..b91cafa --- /dev/null +++ b/script/api.js @@ -0,0 +1,46 @@ +const API_KEY = 'a65c4ce8fc964aa6ab9618a0da2629db' +const LEAGUE_ID = 2021 + +var base_url = "https://api.football-data.org/v2/"; +var urlKlasemen = `${base_url}competitions/${LEAGUE_ID}/standings` +var urlTim = `${base_url}competitions/${LEAGUE_ID}/teams` + +var fetchApi = url => { + return fetch(url, { + headers: { + 'X-Auth-Token': API_KEY + } + }); +} + +var status = response => { + if (response.status !== 200) { + console.log("Error : " + response.status); + + return Promise.reject(new Error(response.statusText)); + } else { + return Promise.resolve(response); + } +} + +var json = response => { + return response.json(); +} + +var error = error => { + console.log("Error: " + error); +} + +var getKlasemen = () => { + var fetK = fetchApi(urlKlasemen) + .then(status) + .then(json); + return fetK; +} + +var getTim = () => { + var fetT = fetchApi(urlTim) + .then(status) + .then(json); + return fetT; +} \ No newline at end of file diff --git a/script/idb.js b/script/idb.js new file mode 100644 index 0000000..1fc7dca --- /dev/null +++ b/script/idb.js @@ -0,0 +1,316 @@ +'use strict'; + +(function() { + function toArray(arr) { + return Array.prototype.slice.call(arr); + } + + function promisifyRequest(request) { + return new Promise(function(resolve, reject) { + request.onsuccess = function() { + resolve(request.result); + }; + + request.onerror = function() { + reject(request.error); + }; + }); + } + + function promisifyRequestCall(obj, method, args) { + var request; + var p = new Promise(function(resolve, reject) { + request = obj[method].apply(obj, args); + promisifyRequest(request).then(resolve, reject); + }); + + p.request = request; + return p; + } + + function promisifyCursorRequestCall(obj, method, args) { + var p = promisifyRequestCall(obj, method, args); + return p.then(function(value) { + if (!value) return; + return new Cursor(value, p.request); + }); + } + + function proxyProperties(ProxyClass, targetProp, properties) { + properties.forEach(function(prop) { + Object.defineProperty(ProxyClass.prototype, prop, { + get: function() { + return this[targetProp][prop]; + }, + set: function(val) { + this[targetProp][prop] = val; + } + }); + }); + } + + function proxyRequestMethods(ProxyClass, targetProp, Constructor, properties) { + properties.forEach(function(prop) { + if (!(prop in Constructor.prototype)) return; + ProxyClass.prototype[prop] = function() { + return promisifyRequestCall(this[targetProp], prop, arguments); + }; + }); + } + + function proxyMethods(ProxyClass, targetProp, Constructor, properties) { + properties.forEach(function(prop) { + if (!(prop in Constructor.prototype)) return; + ProxyClass.prototype[prop] = function() { + return this[targetProp][prop].apply(this[targetProp], arguments); + }; + }); + } + + function proxyCursorRequestMethods(ProxyClass, targetProp, Constructor, properties) { + properties.forEach(function(prop) { + if (!(prop in Constructor.prototype)) return; + ProxyClass.prototype[prop] = function() { + return promisifyCursorRequestCall(this[targetProp], prop, arguments); + }; + }); + } + + function Index(index) { + this._index = index; + } + + proxyProperties(Index, '_index', [ + 'name', + 'keyPath', + 'multiEntry', + 'unique' + ]); + + proxyRequestMethods(Index, '_index', IDBIndex, [ + 'get', + 'getKey', + 'getAll', + 'getAllKeys', + 'count' + ]); + + proxyCursorRequestMethods(Index, '_index', IDBIndex, [ + 'openCursor', + 'openKeyCursor' + ]); + + function Cursor(cursor, request) { + this._cursor = cursor; + this._request = request; + } + + proxyProperties(Cursor, '_cursor', [ + 'direction', + 'key', + 'primaryKey', + 'value' + ]); + + proxyRequestMethods(Cursor, '_cursor', IDBCursor, [ + 'update', + 'delete' + ]); + + // proxy 'next' methods + ['advance', 'continue', 'continuePrimaryKey'].forEach(function(methodName) { + if (!(methodName in IDBCursor.prototype)) return; + Cursor.prototype[methodName] = function() { + var cursor = this; + var args = arguments; + return Promise.resolve().then(function() { + cursor._cursor[methodName].apply(cursor._cursor, args); + return promisifyRequest(cursor._request).then(function(value) { + if (!value) return; + return new Cursor(value, cursor._request); + }); + }); + }; + }); + + function ObjectStore(store) { + this._store = store; + } + + ObjectStore.prototype.createIndex = function() { + return new Index(this._store.createIndex.apply(this._store, arguments)); + }; + + ObjectStore.prototype.index = function() { + return new Index(this._store.index.apply(this._store, arguments)); + }; + + proxyProperties(ObjectStore, '_store', [ + 'name', + 'keyPath', + 'indexNames', + 'autoIncrement' + ]); + + proxyRequestMethods(ObjectStore, '_store', IDBObjectStore, [ + 'put', + 'add', + 'delete', + 'clear', + 'get', + 'getAll', + 'getKey', + 'getAllKeys', + 'count' + ]); + + proxyCursorRequestMethods(ObjectStore, '_store', IDBObjectStore, [ + 'openCursor', + 'openKeyCursor' + ]); + + proxyMethods(ObjectStore, '_store', IDBObjectStore, [ + 'deleteIndex' + ]); + + function Transaction(idbTransaction) { + this._tx = idbTransaction; + this.complete = new Promise(function(resolve, reject) { + idbTransaction.oncomplete = function() { + resolve(); + }; + idbTransaction.onerror = function() { + reject(idbTransaction.error); + }; + idbTransaction.onabort = function() { + reject(idbTransaction.error); + }; + }); + } + + Transaction.prototype.objectStore = function() { + return new ObjectStore(this._tx.objectStore.apply(this._tx, arguments)); + }; + + proxyProperties(Transaction, '_tx', [ + 'objectStoreNames', + 'mode' + ]); + + proxyMethods(Transaction, '_tx', IDBTransaction, [ + 'abort' + ]); + + function UpgradeDB(db, oldVersion, transaction) { + this._db = db; + this.oldVersion = oldVersion; + this.transaction = new Transaction(transaction); + } + + UpgradeDB.prototype.createObjectStore = function() { + return new ObjectStore(this._db.createObjectStore.apply(this._db, arguments)); + }; + + proxyProperties(UpgradeDB, '_db', [ + 'name', + 'version', + 'objectStoreNames' + ]); + + proxyMethods(UpgradeDB, '_db', IDBDatabase, [ + 'deleteObjectStore', + 'close' + ]); + + function DB(db) { + this._db = db; + } + + DB.prototype.transaction = function() { + return new Transaction(this._db.transaction.apply(this._db, arguments)); + }; + + proxyProperties(DB, '_db', [ + 'name', + 'version', + 'objectStoreNames' + ]); + + proxyMethods(DB, '_db', IDBDatabase, [ + 'close' + ]); + + // Add cursor iterators + // TODO: remove this once browsers do the right thing with promises + ['openCursor', 'openKeyCursor'].forEach(function(funcName) { + [ObjectStore, Index].forEach(function(Constructor) { + // Don't create iterateKeyCursor if openKeyCursor doesn't exist. + if (!(funcName in Constructor.prototype)) return; + + Constructor.prototype[funcName.replace('open', 'iterate')] = function() { + var args = toArray(arguments); + var callback = args[args.length - 1]; + var nativeObject = this._store || this._index; + var request = nativeObject[funcName].apply(nativeObject, args.slice(0, -1)); + request.onsuccess = function() { + callback(request.result); + }; + }; + }); + }); + + // polyfill getAll + [Index, ObjectStore].forEach(function(Constructor) { + if (Constructor.prototype.getAll) return; + Constructor.prototype.getAll = function(query, count) { + var instance = this; + var items = []; + + return new Promise(function(resolve) { + instance.iterateCursor(query, function(cursor) { + if (!cursor) { + resolve(items); + return; + } + items.push(cursor.value); + + if (count !== undefined && items.length == count) { + resolve(items); + return; + } + cursor.continue(); + }); + }); + }; + }); + + var exp = { + open: function(name, version, upgradeCallback) { + var p = promisifyRequestCall(indexedDB, 'open', [name, version]); + var request = p.request; + + if (request) { + request.onupgradeneeded = function(event) { + if (upgradeCallback) { + upgradeCallback(new UpgradeDB(request.result, event.oldVersion, request.transaction)); + } + }; + } + + return p.then(function(db) { + return new DB(db); + }); + }, + delete: function(name) { + return promisifyRequestCall(indexedDB, 'deleteDatabase', [name]); + } + }; + + if (typeof module !== 'undefined') { + module.exports = exp; + module.exports.default = module.exports; + } + else { + self.idb = exp; + } +}()); diff --git a/script/init.js b/script/init.js new file mode 100644 index 0000000..167d89e --- /dev/null +++ b/script/init.js @@ -0,0 +1,4 @@ + document.addEventListener('DOMContentLoaded', function () { + var elems = document.querySelectorAll('.sidenav'); + var instances = M.Sidenav.init(elems); + }); diff --git a/script/jquery-2.1.1.min.js b/script/jquery-2.1.1.min.js new file mode 100644 index 0000000..9ed2acc --- /dev/null +++ b/script/jquery-2.1.1.min.js @@ -0,0 +1,4 @@ +/*! jQuery v2.1.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l=a.document,m="2.1.1",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return!n.isArray(a)&&a-parseFloat(a)>=0},isPlainObject:function(a){return"object"!==n.type(a)||a.nodeType||n.isWindow(a)?!1:a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf")?!1:!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=l.createElement("script"),b.text=a,l.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:k}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+-new Date,v=a.document,w=0,x=0,y=gb(),z=gb(),A=gb(),B=function(a,b){return a===b&&(l=!0),0},C="undefined",D=1<<31,E={}.hasOwnProperty,F=[],G=F.pop,H=F.push,I=F.push,J=F.slice,K=F.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},L="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",N="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=N.replace("w","w#"),P="\\["+M+"*("+N+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+O+"))|)"+M+"*\\]",Q=":("+N+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+P+")*)|.*)\\)|)",R=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),S=new RegExp("^"+M+"*,"+M+"*"),T=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),V=new RegExp(Q),W=new RegExp("^"+O+"$"),X={ID:new RegExp("^#("+N+")"),CLASS:new RegExp("^\\.("+N+")"),TAG:new RegExp("^("+N.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+Q),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{I.apply(F=J.call(v.childNodes),v.childNodes),F[v.childNodes.length].nodeType}catch(eb){I={apply:F.length?function(a,b){H.apply(a,J.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],!a||"string"!=typeof a)return d;if(1!==(k=b.nodeType)&&9!==k)return[];if(p&&!e){if(f=_.exec(a))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return I.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return I.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=9===k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+qb(o[l]);w=ab.test(a)&&ob(b.parentNode)||b,x=o.join(",")}if(x)try{return I.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function gb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function hb(a){return a[u]=!0,a}function ib(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function jb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function kb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||D)-(~a.sourceIndex||D);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function lb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function nb(a){return hb(function(b){return b=+b,hb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function ob(a){return a&&typeof a.getElementsByTagName!==C&&a}c=fb.support={},f=fb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fb.setDocument=function(a){var b,e=a?a.ownerDocument||a:v,g=e.defaultView;return e!==n&&9===e.nodeType&&e.documentElement?(n=e,o=e.documentElement,p=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){m()},!1):g.attachEvent&&g.attachEvent("onunload",function(){m()})),c.attributes=ib(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ib(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(e.getElementsByClassName)&&ib(function(a){return a.innerHTML="
    ",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=ib(function(a){return o.appendChild(a).id=u,!e.getElementsByName||!e.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==C&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c=typeof a.getAttributeNode!==C&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==C?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==C&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(e.querySelectorAll))&&(ib(function(a){a.innerHTML="",a.querySelectorAll("[msallowclip^='']").length&&q.push("[*^$]="+M+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+M+"*(?:value|"+L+")"),a.querySelectorAll(":checked").length||q.push(":checked")}),ib(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+M+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ib(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",Q)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===v&&t(v,a)?-1:b===e||b.ownerDocument===v&&t(v,b)?1:k?K.call(k,a)-K.call(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],i=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:k?K.call(k,a)-K.call(k,b):0;if(f===g)return kb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?kb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},e):n},fb.matches=function(a,b){return fb(a,null,null,b)},fb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fb(b,n,null,[a]).length>0},fb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&E.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fb.selectors={cacheLength:50,createPseudo:hb,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+M+")"+a+"("+M+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==C&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?hb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=K.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:hb(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?hb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:hb(function(a){return function(b){return fb(a,b).length>0}}),contains:hb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:hb(function(a){return W.test(a||"")||fb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:nb(function(){return[0]}),last:nb(function(a,b){return[b-1]}),eq:nb(function(a,b,c){return[0>c?c+b:c]}),even:nb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:nb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:nb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:nb(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function rb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function sb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function tb(a,b,c){for(var d=0,e=b.length;e>d;d++)fb(a,b[d],c);return c}function ub(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function vb(a,b,c,d,e,f){return d&&!d[u]&&(d=vb(d)),e&&!e[u]&&(e=vb(e,f)),hb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||tb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ub(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ub(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?K.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ub(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):I.apply(g,r)})}function wb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=rb(function(a){return a===b},h,!0),l=rb(function(a){return K.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>i;i++)if(c=d.relative[a[i].type])m=[rb(sb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return vb(i>1&&sb(m),i>1&&qb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&wb(a.slice(i,e)),f>e&&wb(a=a.slice(e)),f>e&&qb(a))}m.push(c)}return sb(m)}function xb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=G.call(i));s=ub(s)}I.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&fb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?hb(f):f}return h=fb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xb(e,d)),f.selector=a}return f},i=fb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&ob(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qb(j),!a)return I.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&ob(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ib(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ib(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||jb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ib(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||jb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ib(function(a){return null==a.getAttribute("disabled")})||jb(L,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fb}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return g.call(b,a)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:l,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=l.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=l,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};A.prototype=n.fn,y=n(l);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(n(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(C[a]||n.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return n.each(a.match(E)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&n.each(arguments,function(a,b){var c;while((c=n.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(H.resolveWith(l,[n]),n.fn.triggerHandler&&(n(l).triggerHandler("ready"),n(l).off("ready"))))}});function I(){l.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),n.ready()}n.ready.promise=function(b){return H||(H=n.Deferred(),"complete"===l.readyState?setTimeout(n.ready):(l.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},n.ready.promise();var J=n.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)n.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};n.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=n.expando+Math.random()}K.uid=1,K.accepts=n.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,n.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(n.isEmptyObject(f))n.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!n.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){return M.access(a,b,c)},removeData:function(a,b){M.remove(a,b) +},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d])));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=n.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||n.isArray(c)?d=L.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:n.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthx",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";k.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|pointer|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return l.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof n!==U&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,m,o,p=[d||l],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||l,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+n.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},e||!o.trigger||o.trigger.apply(d,c)!==!1)){if(!e&&!o.noBubble&&!n.isWindow(d)){for(i=o.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||l)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:o.bindType||q,m=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),m&&m.apply(g,c),m=k&&g[k],m&&m.apply&&n.acceptData(g)&&(b.result=m.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!n.acceptData(d)||k&&n.isFunction(d[q])&&!n.isWindow(d)&&(h=d[k],h&&(d[k]=null),n.event.triggered=q,d[q](),n.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>=0:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,bb=/<([\w:]+)/,cb=/<|&#?\w+;/,db=/<(?:script|style|link)/i,eb=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/^$|\/(?:java|ecma)script/i,gb=/^true\/(.*)/,hb=/^\s*\s*$/g,ib={option:[1,""],thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};ib.optgroup=ib.option,ib.tbody=ib.tfoot=ib.colgroup=ib.caption=ib.thead,ib.th=ib.td;function jb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function kb(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function lb(a){var b=gb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function mb(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function nb(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=n.extend({},h),M.set(b,i))}}function ob(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function pb(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}n.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=ob(h),f=ob(a),d=0,e=f.length;e>d;d++)pb(f[d],g[d]);if(b)if(c)for(f=f||ob(a),g=g||ob(h),d=0,e=f.length;e>d;d++)nb(f[d],g[d]);else nb(a,h);return g=ob(h,"script"),g.length>0&&mb(g,!i&&ob(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,o=a.length;o>m;m++)if(e=a[m],e||0===e)if("object"===n.type(e))n.merge(l,e.nodeType?[e]:e);else if(cb.test(e)){f=f||k.appendChild(b.createElement("div")),g=(bb.exec(e)||["",""])[1].toLowerCase(),h=ib[g]||ib._default,f.innerHTML=h[1]+e.replace(ab,"<$1>")+h[2],j=h[0];while(j--)f=f.lastChild;n.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===n.inArray(e,d))&&(i=n.contains(e.ownerDocument,e),f=ob(k.appendChild(e),"script"),i&&mb(f),c)){j=0;while(e=f[j++])fb.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f=n.event.special,g=0;void 0!==(c=a[g]);g++){if(n.acceptData(c)&&(e=c[L.expando],e&&(b=L.cache[e]))){if(b.events)for(d in b.events)f[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);L.cache[e]&&delete L.cache[e]}delete M.cache[c[M.expando]]}}}),n.fn.extend({text:function(a){return J(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(ob(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&mb(ob(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(ob(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!db.test(a)&&!ib[(bb.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ab,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(ob(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(ob(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,m=this,o=l-1,p=a[0],q=n.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&eb.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(c=n.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=n.map(ob(c,"script"),kb),g=f.length;l>j;j++)h=c,j!==o&&(h=n.clone(h,!0,!0),g&&n.merge(f,ob(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,n.map(f,lb),j=0;g>j;j++)h=f[j],fb.test(h.type||"")&&!L.access(h,"globalEval")&&n.contains(i,h)&&(h.src?n._evalUrl&&n._evalUrl(h.src):n.globalEval(h.textContent.replace(hb,"")))}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),n(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qb,rb={};function sb(b,c){var d,e=n(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:n.css(e[0],"display");return e.detach(),f}function tb(a){var b=l,c=rb[a];return c||(c=sb(a,b),"none"!==c&&c||(qb=(qb||n("